Spring AOP的术语
- 通知(advice):定义了切面的功能和调用的时机
通知分为:前置通知(Before)、后置通知(After)、返回通知(After-returning)、异常通知(After-throwing)、环绕通知(Around) - 连接点(join point):定义了所有需要插入通知的点
- 切点(Pointcut):定义了何处插入通知,是连接点的子集,切点的定义会匹配所要织入的一个或多个连接点
- 切面(Aspect):是切点和通知的集合
Spring AOP与AspectJ
- AspectJ还支持属性与构造器的连接点,SpringAOP只支持方法的连接点
- AspectJ支持编译期、类加载期、运行期三种方式的AOP实现,Spring AOP只支持运行期的AOP实现
编译期:AOP切面在编译期织入目标,需织入编译器支持
类加载器:AOP切面在类加载时织入目标,需要特殊的类加载器
运行期:为目标动态创建一个代理对象来织入切面(所以只支持方法级)
引入与织入
- 引入(Introduction):允许我们向现有类添加新方法或属性
- 织入(Weaving):把切面应用到目标对象并创建新的代理对象
JavaConfig方式配置AOP
-
配置切面
`@Aspect
public class Audience {
//@Pointcut能够使不用在每个织入方法上写上"excution"的切点
@Pointcut(“excution(** concert.Performance.perform(…))”)
public void performance(){}//@Before指定通知advice的调用时机,"excution"指定切点
//因为有配置@Pointcut,这里可用@Before(“performance()”)简化
@Before(“excution(** concert.Performance.perform(…))”)
public void silenceCellPhones() {
…
}//注意环绕通知有个ProceedingJoinPoint类型的入参
//注意当目标方法需要参数(int trackNumber)时,参数的传递方式
@Around(“excution(** concert.Performance.perform2(int)) && args(trackNumber)”)
public void watchPerformance(ProceedingJoinPoint jp, int trackNumber) {
try {
…
jp.proceed(trackNumber);
…
}catch (Throwable e) {
…
}
}
}` -
使能SpringAOP,并注入目标bean与切面bean
`@Configuration
@EnableAspectJAutoProxy
public class AOPConfig {
//可用扫描方式注入切面bean与目标bean//注入切面
@Bean
public Audience audience() {
return new Audience();
}
//注入目标bean
…
}
`
引入新功能
Spring AOP 往目标bean引入新功能,是通过当访问代理目标bean的新方法时,导向了被代理包装的新功能方法的实现bean,即一个代理bean代理了两个目标bean
@Aspect public class EncoreableIntroduction { //value 代表目标类,+代表子类 //defaultImpl代表引入新功能的实现 //@DeclareParents一般标注静态属性 @DeclareParents(value="concert.Performance+", defaultImpl=DefaultEncoreable.class) public static Encoreable encoreble; }
JavaConfig与XML配置的选择
当不能用注解配置通知类源码时(通知类源代码不在手中),选用XML