基于@AspectJ配置Spring AOP之一
通过配置织入@AspectJ切面
虽然可以通过编程的方式织入切面,但一般情况下,我们还是使用Spring的配置自动完成创建代理织入切面的工作。
AnnotationAwareAspectJAutoProxyCreator能够将@AspectJ注解切面的自动织入到目标Bean中。这里,PreGreetingAspect是使用了@AspectJ注解描述的切面类,而NaiveWaiter是匹配切点的目标类。<bean id="waiter" class="com.baobaotao.NaiveWaiter" /> ①目标Bean
②使用了@AspectJ注解的切面类
<bean class="com.baobaotao.aspectj.example.PreGreetingAspect" />
③自动代理创建器,自动将@AspectJ注解切面类织入到目标Bean中
<bean class="org.springframework.aop.aspectj.annotation.
AnnotationAwareAspectJAutoProxyCreator"/>
如果使用基于Schema的aop命名空间进行配置,事情就更简单了:
首先,在配置文件中引入aop命名空间,如①、②处所示,然后通过aop命名空间的<aop:aspectj-autoproxy />声明自动为Spring容器中那些匹配@AspectJ切面的Bean创建代理,织入切面。当然,Spring在内部依旧采用AnnotationAwareAspectJAutoProxyCreator进行自动代理的创建工作,但具体实现的细节已经被<aop:aspectj-autoproxy />隐藏起来了。<?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:aop="http://www.springframework.org/schema/aop" ①
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop ②
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
<aop:aspectj-autoproxy /> ③基于@AspectJ切面的驱动器
<bean id="waiter" class="com.baobaotao.NaiveWaiter" />
<bean class="com.baobaotao.aspectj.example.PreGreetingAspect" />
</beans>
<aop:aspectj-autoproxy />有一个proxy-target-class属性,默认为false,表示使用JDK动态代理织入增强,当配置为<aop:aspectj-autoproxy proxy-target-class="true" />时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则Spring将自动使用CGLib动态代理。
@AspectJ语法基础
@AspectJ使用JDK 5.0注解和正规的AspectJ 5的切点表达式语言描述切面,由于Spring只支持方法的连接点,所以Spring仅支持部分AspectJ的切点语言。在这节时,我们将对AspectJ切点表达式语言进行必要的学习。
切点表达式函数
AspectJ 5的切点表达式由关键字和操作参数组成,如execution(* greetTo(..))的切点表达式,“execute”为关键字,而“* greetTo(..)”为操作参数。在这里,execute代表目标类执行某一方法,而“* greetTo(..)”是描述目标方法的匹配模式串,两者联合起来所表示的切点匹配目标类greetTo()方法的连接点。为了描述方便,我们将execution()称作函数,而将匹配串“* greetTo(..)”称作函数的入参。
Spring支持9个@ApsectJ切点表达式函数,它们用不同的方式描述目标类的连接点,根据描述对象的不同,可以将它们大致分为4种类型:
方法切点函数:通过描述目标类方法信息定义连接点;
方法入参切点函数:通过描述目标类方法入参的信息定义连接点;
目标类切点函数:通过描述目标类类型信息定义连接点;
代理类切点函数:通过描述目标类的代理类的信息定义连接点;
这4种类型的切点函数,通过表 1进行说明:
表 1 切点函数
|
类别
|
函数
|
入参
|
说明
|
|
方法切点函数
|
execution()
|
方法
匹配模式串
|
表示满足某一匹配模式的所有目标类方法连接点。如execution(* greetTo(..))表示所有目标类中的greetTo()方法。
|
|
@annotation()
|
方法注
解类名
|
表示标注了特定注解的目标方法连接点。如@annotation(com.baobaotao.anno.NeedTest)表示任何标注了@NeedTest注解的目标类方法。
|
|
|
方法入参切点函数
|
args()
|
类名
|
通过判别目标类方法运行时入参对象的类型定义指定连接点。如args(com.baobaotao.Waiter)表示所有有且仅有一个按类型匹配于Waiter的入参的方法。
|
|
@args()
|
类型注
解类名
|
通过判别目标方法的运行时入参对象的类是否标注特定注解来指定连接点。如@args(com.baobaotao.Monitorable)表示任何这样的一个目标方法:它有一个入参且入参对象的类标注@Monitorable注解。
|
|
|
目标类切点函数
|
within()
|
类名匹配串
|
表示特定域下的所有连接点。如within(com.baobaotao.service.*)表示com.baobaotao.service包中的所有连接点,也即包中所有类的所有方法,而within(com.baobaotao.service.*Service)表示在com.baobaotao.service包中,所有以Service结尾的类的所有连接点。
|
|
target()
|
类名
|
假如目标类按类型匹配于指定类,则目标类的所有连接点匹配这个切点。如通过target(com.baobaotao.Waiter)定义的切点,Waiter、以及Waiter实现类NaiveWaiter中所有连接点都匹配该切点。
|
|
|
@within()
|
类型注解类名
|
假如目标类按类型匹配于某个类A,且类A标注了特定注解,则目标类的所有连接点匹配这个切点。
如@within(com.baobaotao.Monitorable)定义的切点,假如Waiter类标注了@Monitorable注解,则Waiter以及Waiter实现类NaiveWaiter类的所有连接点都匹配。
|
|
|
@target()
|
类型注解类名
|
目标类标注了特定注解,则目标类所有连接点匹配该切点。如@target(com.baobaotao.Monitorable),假如NaiveWaiter标注了@Monitorable,则NaiveWaiter所有连接点匹配切点。
|
|
|
代理类切点函数
|
this()
|
类名
|
代理类按类型匹配于指定类,则被代理的目标类所有连接点匹配切点。这个函数比较难理解,这里暂不举例,留待后面详解。
|
@AspectJ除上表中所列的函数外,还有call()、initialization()、 preinitialization()、 staticinitialization()、 get()、 set()、handler()、 adviceexecution()、 withincode()、 cflow()、 cflowbelow()、 if()、 @this()以及@withincode()等函数,这些函数在Spring中不能使用,否则会抛出IllegalArgumentException异常。在不特别声明的情况下,本书中所讲@AspectJ函数均指表 1中所列的函数。
0
相关文章
