Spring AOP术语/概念
Aspect(切面)
业务流程运行的某个特定步骤,也就是应用运行过程的关注点,关注点通常会横切多个对象,因此常被称为横切关注点
JoinPoint(连接点)
程序执行过程中明确的点,如方法调用,或者异常抛出
Advice(增强)
AOP框架在特定的切入点执行的增强处理。处理有around,before,after等类型
PointCut(切入点)
可以插入增强处理的连接点
引入
将方法或字段添加到被处理的类中。Spring允许引入新的接口到任何被处理的对象
目标对象
被AOP框架进行增强处理的对象,也被称为增强的对象。
AOP代理
AOP框架创建的对象,简单地说,代理就是对目标的对象的加强。Spring中AOP代理可以是JDK动态代理,也可以是CGLIB代理。前者为实现接口的目标对象的代理,后者为不实现接口的目标对象的代理,Spring默认支持使用JDK动态代理来创建AOP代理, 在需要代理类而不是代理接口的时候,Spring自动会切换为使用CGLIB代理
Spring中AOP代理由Spring的IoC容器负责生成、管理。其依赖关系也由IoC容器负责管理。
织入(Weaving)
将增强处理添加到目标对象中,并创建一个被增强的对象(AOP代理)的过程就是织入。织入有两种实现方式:编译时增强(如AspectJ)和运行时增强(如CGLIB)。Spring和其他纯Java AOP框架一样,在运行时织入。
Spring AOP的增强类型
- @Before
- @After
- @AfterReturning
- @AfterThrowing
执行顺序为:Around-> Before -> Around -> After -> AfterReturning
对于应用于统一切点的来自多个类的增强,优先级根据类来决定(@Order注解或者实现Spring的order接口的getOrder()返回值,值越小,优先级越高)
After与AfterReturning的区别: 无论After拦截的方法是否抛出异常,After增强都会被执行,AfterReturning只有当被拦截方法成功执行才会执行
@Pointcut注解可用于切面表达式重用
在Advice方法中获取目标方法的参数
- 通过JoinPoint or ProceedingJoinPoint对象获取
- 通过args(param1, param2, ..)表达式, args表达式有如下两个作用:
- 提供一种简单的方式来访问目标方法的参数
- 对切入点表达式做额外的限制
基于annotation的AOP配置方式
启动对aop注解的支持的两种方式:
- <aop:aspectj-autoproxy/>
- <bean class=“org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator” />
相关注解:
- @Aspect
- @Before
- @Around(可以决定什么时候执行目标方法,甚至不调用目标方法,还可以修改目标方法的参数及返回值Q: 需要工作在线程安全模式下?)
- @After(无论目标方法如何结束,该增强都会执行)
- @AfterReturning(该注解的returnValue属性限定切点表达式所匹配的方法的返回值,虽然AfterReturning增强处理可以访问到目标方法的返回值,但它不可改变这个返回值, 只有在目标方法正确完成后才会被织入)
- @AfterThrowing(该注解的throwing属性用于获取目标方法抛出的异常,增强方法形参中指定的throwing类型将限定该增强所应用的异常类型,AfterThrowing处理虽然处理了该异常,但它不能完全处理该异常,这个异常依然会传播到上一级调用者)
基于XML的AOP配置方式
请参考如下示例:
<bean id="loginLogger" class="me.wmn.log.LoginLogger"/>
<aop:config>
<aop:aspect id="login" ref="loginLogger">
<aop:pointcut id="login" expression="execution(* me.wmn.controller.LoginController.login(..))" />
<aop:after method=“afterAdvice” pointcut-ref="login"/>
<aop:before method="beforeAdvice” pointcut-ref=“login”/>
<aop:after-returning method=“afterReturningAdvice” pointcut=“execution(* me.wmn.controller.LoginController.login(..))”/>
<aop:after-throwing method=“afterThrowingAdvice” pointcut=“execution(* me.wmn.controller.LoginController.login(..))”/>
<aop:after-throwing method=“aroundAdvice” pointcut=“execution(* me.wmn.controller.LoginController.login(..))”/>
</aop:aspect>
</aop:config>
切入点表达式/切点指示符
execution
用于匹配执行方法的连接点,这是Spring AOP中最主要的切入点指示符。execution表达式的格式如下:
execution(modifier-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
- modifier-pattern:指定方法的修饰符,支持通配符,该部分可以省略
- ret-type-pattern:指定返回值类型,支持通配符,可以使用“*”来通配所有的返回值类型
- declaring-type-pattern:指定方法所属的类,支持通配符,该部分可以省略
- name-pattern:指定匹配的方法名,支持通配符,可以使用“*”来通配所有的方法名
- param-pattern:指定方法的形参列表,支持两个通配符,“*”和“..”,其中“*”代表一个任意类型的参数,而“..”代表0个或多个任意类型的参数。
- throw-pattern:指定方法声明抛出的异常,支持通配符,该部分可以省略
within
限定匹配特定类型的连接点,当使用Spring AOP的时候,只能匹配方法执行的连接点。
this
用于指定AOP代理必须是指定类型的实例,用于匹配该对象的所有连接点
target
用于限定目标对象必须是指定类型的实例,用于匹配该对象的所有连接点
args
用于对连接点的参数类型进行限制,要求参数的类型时指定类型的实例
bean
用于指定只匹配该Bean实例内的连接点,实际上只能使用方法执行作为连接点。
组合使用切点表达式
&& 要求连接点同时匹配两个切点表达式
|| 要求连接点匹配至少一个切入点表达式
!要求连接点不匹配指定的切入点表达式