首先了解什么是面向切面编程,这里不做描述。
1.Spring对AOP的支持
Spring提供了4种类型的AOP支持
① 基于代理的经典Spring AOP
② 纯POJO切面
③ @AspectJ 注解驱动的切面
④ 注入式AspectJ 切面
Spring AOP构建在动态代理之上,所以Spring对AOP的支持局限于方法拦截。
Spring在运行时通知对象:通过在代理类中包裹切面,Spring在运行期把切面织入到Spring管理的bean中。代理类封装了目标类,并拦截被通知方法的调用,当拦截到目标方法被调用时,代理类会在目标方法执行前执行切面逻辑。
2.通过切点来选择连接点
切点用于定位在什么位置应用切面的通知。Spring借助ASpectJ 的切点表达式语言来定义Spring切面。
AspectJ指示器 描述
arg() 限制连接点匹配参数为指定类型的执行方法
@args() 限制连接点匹配参数由指定注解标注的执行方法
execution() 用于匹配是连接点的执行方法
this() 限制连接点匹配的AOP代理的bean引用为指定类型的类
target() 限定连接点匹配目标对象为指定类型的类对象
within () 限制连接点匹配指定的类型
@within() 限制连接点匹配指定注解所标注的类型
@annotation 限定匹配带有指定注解的连接点
2.1编写切入点
定义一个Performance接口
package concert;
public interface Performance{
public void perform();
}
编写perform()方法执行时触发的通知的切点表达式,execution(* concert.Performance.perform(..) ).这个表达式能够设置当perform()方法执行时触发通知的调用。这里使用了execution()指示器选择Performance的perform()方法。方法表达式以*开始,表明不关心方法的返回值的类型,然后指定方法的全限定类名和方法名,参数列表使用了 . . 表示切点要选择任意的perform()方法,无论方法的入参是什么。
假设现在需要配置切点仅匹配concert包,可以使用within()指示器来限制匹配,
execution(* concert.Performance.perform(..) && within(concert.*))
XML中使用and替代&&
3.创建切面
可以使用@AspectJ注解定义切面类。
比如需要在上面的Performance接口的perform()方法执行一些通知。比如前置通知后置通知等,可以定义如下的切面。
package concert;
@AspectJ
public class Audience{
//前置通知
@Before("execution(* concert.Performance.perform(..))")
public void before(){
System.out.println("表演开始前");
}
//后置通知
@After("execution(* concert.Performance.perform(..))")
public void after(){
System.out.println("表演已经结束");
}
//异常通知
@AfterThrowing("execution(* concert.Performance.perform(..))")
public void afterThrow(){
System.out.println("方法执行发生异常后执行");
}
}
上面定义了一个切面,但是Spring并不会把它作为切面,还需要做下面的配置。下面使用JavaConfig进行配置。
package concert;
/**
* Java配置类,启动扫描,启动AspectJ自动代理
*
*/
@Configuration
@EnableAspectJ //启动AspectJ自动代理
@ComponetScan
public class ConcertConfig{
@Bean
public Audience audience(){
return new Audience();
}
}
这样,每次在perform()方法前后及发生异常都会执行切面里面定义的通知方法。
这里需要注意一下环绕通知的定义。如下定义了方法的环绕通知。(注意其中的 ProceedingJoinPoint类型参数)
@Around("execution(* concert.Performance.perform(..))")
public void around(ProceedingJoinPoint pj){
System.out.print("环绕通知。。。。");
try{
pj.proceed();
}catch(Exception e){
}
System.out.println("环绕通知。。。。");
}
如果
pj.proceed()不调用此方法则目标方法perform不会被执行。
4.使用XML配置切面及通知
Spring AOP的配置元素必须在
元素的上下文中使用。
首先声明一个类:
然后在
元素中将上述声明的类引用为切面,并且定义切点等。