转发地址:https://www.iteye.com/blog/elim-2394762

2 基于Aspectj注解的Spring Aop简单实现

Spring Aop是基于Aop框架Aspectj实现的,它不是完完全全的对Aspectj框架进行扩展和改造,而是利用Aspectj里面的一些功能来实现自己的Aop框架,其中就包括对Aspectj提供的注解的解析。之前已经提过Spring Aop和Aspectj实现的Aop之间的差别,这里就不再赘述。本文主要描述的是如何利用Aspectj提供的注解来实现Spring Aop功能,旨在让大家对Spring Aop、对使用Aspectj注解开发Spring Aop有一个初步印象。

2.1 启用对Aspectj注解的支持

使用Aspectj注解来实现Spring Aop时我们首先需要启用Spring对Aspectj注解支持的功能,这是通过配置来进行的。当我们的Spring配置是以配置文件为主时,我们可以通过在Spring的配置文件中引入aop相关的schema,然后通过<aop:aspectj-autoproxy/>来启用对Aspectj注解的支持。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:annotation-config/>
<context:component-scan base-package="com.elim.test"/>
<!-- 启用对Aspectj注解的支持 -->
<aop:aspectj-autoproxy/> </beans>

当我们的配置是通过使用@Configuration标注的配置类来进行的时候,我们就可以通过在该配置类上使用@EnableAspectJAutoProxy进行标注来启用对Aspectj注解的支持。

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration
@EnableAspectJAutoProxy
public class AppConfig { }

2.2 定义切面类

定义切面类比较简单,只需要定义一个简单的使用@Aspect进行标注的类即可。@Aspect是Spring Aop识别切面类的一个标记,但是光使用@Aspect对切面类进行标注还不行。因为Spring Aop只能对定义在bean容器中的bean发生作用,对应的切面类也必须是定义在bean容器中的bean对象时其才能发现。@Aspect不具备默认让Spring扫描到它,把对应的类实例化为Spring bean的功能,所以我们必须要在bean容器中定义该bean。可以通过配置文件定义,也可以通过使用@Component进行标注等。

@Aspect
@Component
public class MyAspect { }

使用@Aspect标注的切面类也可以像普通类一样定义普通的属性和方法,如果有需要也可以把它当做一个普通的bean使用。

2.3 定义Pointcut

Pointcut是用来定义切面类需要作用的JoinPoint的,在Spring Aop中这些JoinPoint其实就是一些我们需要进行切入的方法执行,因为之前我们说过Spring Aop只支持对bean方法执行的切入。基于Aspect注解形式定义的Pointcut的核心是@Pointcut注解,我们需要在Aspect类中定义一个没有返回值的方法,方法类型可任意,然后在该方法上使用@Pointcut进行标注,表示其是一个Pointcut定义,对应的方法名即表示该Pointcut的名称。@Pointcut有一个value属性,其通常是一个表达式,通过它可以指定当前Pointcut需要作用的JoinPoint。表达式可以有很多种写法,这个在后续会专门讲解,通常用的最多的就是execution,表示方法的执行。如我们想定义一个Pointcut的JoinPoint为所有add方法的执行,那么我们可以如下定义。

@Aspect
@Component
public class MyAspect { @Pointcut("execution(* add(..))")
private void pointcut() {} }

2.4 定义Advice

Advice需要与Pointcut绑定在一起,用以定义需要在指定的Pointcut匹配的JoinPoint处执行的操作。Advice主要有三种类型,before、after和around,Aspectj对它们都有对应的注解进行支持。基于Aspectj注解的advice定义是通过对应的注解来指定的,我们需要在切面类中定义一个方法,然后在该方法上使用对应的注解进行标注。对应的advice注解都有一个value属性,我们需要通过它来指定与之绑定的Pointcut,对应的Pointcut需要通过Pointcut定义的类全名称.方法名()来指定,如果是在当前切面类中定义的Pointcut则可以省略对应的类名称。这里主要拿before来做一个示例,如下,我们在切面类中定义了一个方法before,并用@Before注解标注了该方法,同时指定了其所绑定的Pointcut为同一个切面类中定义的pointcut。

@Aspect
@Component
public class MyAspect { @Pointcut("execution(* add(..))")
private void pointcut() {} @Before("com.elim.test.spring.aop.MyAspect.pointcut()")
private void before(JoinPoint joinPoint) {
System.out.println(joinPoint.getTarget() + "----------------------Before---------------------");
} }

至此,当我们在访问Spring bean容器中任意bean对象的add方法前就会调用MyAspect切面类中定义的before方法了。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest { @Autowired
private UserService userService; @Test
public void test1() {
User user = new User(1, "ZhangSan");
userService.add(user);
} }

(注:本文是基于Spring4.1.0所写,写于2016年9月5日星期一)

最新文章

  1. C++STL -- vector 使用
  2. DHCP工作过程
  3. Hibernate,JPA注解@OneToMany_Set
  4. Js 变量的作用域
  5. [Bootstrap] 2. class &#39;row&#39; &amp; &#39;col-md-x&#39; &amp; &#39;col-md-offset-x&#39;
  6. 与众不同 windows phone (23) - Device(设备)之硬件状态, 系统状态, 网络状态
  7. 基于C++ 苹果apns消息推送实现(2)
  8. IdentityServer Topics(2)- 定义资源
  9. [BZOJ1002] [FJOI2007] 轮状病毒 (数学)
  10. 洛谷P2516 [HAOI2010]最长公共子序列(LCS,最短路)
  11. System.currentTimeMillis()方法
  12. Python2.6 升级2.7
  13. 一个java版本的简单邮箱小爬虫
  14. com.alibaba.com.caucho.hessian.io.SerializerFactory getDeserializer
  15. What is Druid?
  16. Hadoop HBase概念学习系列之RowKey设计(二十九)
  17. spring data 自定义接口
  18. nginx添加新模块
  19. [SHELL]软件管理
  20. java的异常分类

热门文章

  1. 2018/7/31--zznu-oj-问题 G: 方差 普拉斯--【两重暴力循环求方差即可!】
  2. vue 有条件加载组件 执行某方法后再渲染组件
  3. 希尔排序Shell_Sort
  4. 使用 EasyExcel 写Excel数据(表头动态)
  5. python面向对象基础(四)内置方法 __xx__之new与init
  6. 2019牛客暑期多校训练营(第七场)D Number——实系数多项式因式分解定理
  7. redis使用例子
  8. 用pyinstaller打包python程序、打包pyqt程序
  9. The Preliminary Contest for ICPC Asia Xuzhou 2019 【 题目:so easy】{并查集维护一个数的下一个没有被删掉的数} 补题ING
  10. python define function