1、AspectJ 补充了SpringAOP的功能.
2、AOP术语:
通知 advice:就等于用于切面的方法
连接点 join point: 在方法的什么时候通知,比如调用前,抛出异常时,甚至修改一个字段时。
切点 poincut: 明确或者正则来匹配在哪些类,哪些方法名,来应用通知。
切面 Aspect:通知和切点组成了一个切面。
引入 Introduction:引入允许我们向现有的类添加新方法或属性。
织入 weaving: 织入是把切面应用到目标对象并创建新的代理对象的过程。
编译时织入:需要特殊的编译器,AspectJ就时用这种方式织入
类加载器: 需要特殊的类加载器,AspectJ5 (load-time weaving)LTW支持这种方式
运行期: 运行期动态创建一个代理类,来完成织入SpringAOP的做法。
3、Spring 提供了4中类型的AOP支持 (Spring大量借鉴了AspectJ)
*基于代理的经典SpringAOP
*纯POJO 切面 (本质上还是基于代理的AOP,需要XML 配置)
*@AspectJ注解驱动的切面 (本质上还是基于代理的AOP,但是可以用类似AspectJ的方式,以注解的方式完成配置)
@注入式AspectJ切面(适用于Spring各版本,如果你的需求不仅仅是简单的方法调用,如构造器和属性拦截)
4、指示器语法
Spring使用了部分的AspectJ指示器。 除了execution是实际执行指示器,其他全是限制指示器。
例1: execution( * com.XXX.method(..) )
第一段 指示器类型,说明在方法执行时触发;第二段 说明返回任意类型;第三段 方法所属的类;第四段 方法名;第五段 代表任何参数
例2: execution( * com.XXX.method(..) ) && within (concert.*)
这种方式,额外增加了一个包限制, 第六段 && 代表(and、和);第七段被限制的包名
类似的 除了&& 和,还可以使用 || 或 ,! 非, 来标识关系。
因为& 在XML中有特殊含义,我们在XML中配置的时候可以使用 and、or、not
例3: execution( * com.XXX.method(..) ) and !bean ('apple')
切面的通知会被织入到所有ID不为 apple的bean中
5、使用注解来创建切面,AspectJ5新特性。
@After 方法返回或抛出异常后调用
@AferReturning 方法返回后调用
@AferThrowing 抛出异常后调用
@Around 将方法包围起来
@before 方法执行前执行
5、创建切面的两种方法
1)例子如下
@Aspect
public class Audience{
@Before("execution(** com.xsx.XXXMehtod(..))")
public void method1(){
Sytem.out.println("excute method1");
}
@AfterThrowing("execution(** com.xsx.XXXMehtod(..))")
public void method2(){
Sytem.out.println("excute method2");
}
}
2)例子如下: 我们发现第一个例子中的指示器相同,这样我们可以把指示器提取出来
@Aspect
public class Audience{
@Pointcut("execution(** com.xsx.XXXMehtod(..))")
public void method(){
//方法体中的内容没有任何意义, 空的就可以
}
@Before("method()")
public void method1(){
Sytem.out.println("excute method1");
}
@AfterThrowing("method()")
public void method2(){
Sytem.out.println("excute method2");
}
}
为了使切面生效,如果我们使用javaConfig的话,我们还需要配置@EnableAspectJAutoProxy;如果使用xml的配置 <aop:aspectJ-autoproxy />
3)例子如下(环绕通知)
@Aspect
public class Audience{
@Pointcut("execution(** com.xsx.XXXMehtod(..))")
public void method(){
//方法体中的内容没有任何意义, 空的就可以
}
@Aroud("method()")
public void watchPerformance(ProceedingJoinPoint jp){
try{
System.out.println("Silencing cell phones");
System.out.println("taking seats");
jp.proceed();
System.out.println("CLAP CLAP CLAP");
}catch(Throwable e){
System.out.pringln("Demanding a refund");
}
}
}
//对于 环绕切面,注意到参数 ProceedingJoinPoint, 执行jp.proceed(),将控制权交给被通知的方法。如果不调用,通知的方法将被阻塞。可以利用这种特性,实现一种逻辑,再被通知方法失败后,进行重复尝试。
环绕通知的另一个好处,
来源:oschina
链接:https://my.oschina.net/u/3018126/blog/3165708