Spring AOP-基本概念以及织入顺序
文章目录
基本概念
在 spring 中 Aspect 通过@Aspect
、@Pointcut
和一系列 advice(@Before
、@after
、@afterReturning
、@Around
)组成。
@Aspect
切面,声明当前 class 为一个切面@Pointcut
切入点,通过 execution 表达式描述切入规则,- advice 通知,定义了切面是什么以及何时使用。
advice 中还包含了 连接点(joinpoint) - weave 织入,将切面应用到目标对象并导致代理对象创建的过程
- introduction 引入,在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法或字段
advice 类型
@Before
前置通知(Before advice):在某连接点(JoinPoint)——被切入代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。因为@Before
注解的方法入参不能传 ProceedingJoinPoint,而只能传入 JoinPoint。而从 aop 走到核心代码就是通过调用 ProceedingJionPoint 的 proceed()方法。而 JoinPoint 没有这个方法。
这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在 JoinPoint 的基础上暴露出 proceed 这个方法。proceed 很重要,这个是 aop 代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到 JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。
@After
后通知(After advice):当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
@AfterReturning
返回后通知(After return advice):在某连接点正常完成后执行的通知,不包括抛出异常的情况。
@Around
环绕通知(Around advice):包围一个连接点的通知,类似 Web 中 Servlet 规范中的 Filter 的 doFilter 方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时 aop 的最重要的,最常用的注解。用这个注解的方法入参传的是 ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用 pjp.proceed();
@AfterThrowing
抛出异常后通知(After throwing advice):在方法抛出异常退出时执行的通知。
advice 注解的执行先后顺序
基础顺序
执行到核心业务方法或者类时,会先执行 AOP。在 aop 的逻辑内,先走@Around
注解的方法。然后是@Before
注解的方法,然后这两个都通过了,走核心代码,核心代码走完,无论核心有没有返回值,都会走@After
方法。然后如果程序无异常,正常返回就走@AfterReturn
,有异常就走@AfterThrowing
。
多个切面顺序
注意点
- 如果在同一个 aspect 类中,针对同一个 pointcut,定义了两个相同的 advice(比如,定义了两个
@Before
),那么这两个 advice 的执行顺序是无法确定的,即使在这两个 advice 添加了@Order
这个注解,也不行。 - 对于@Around 这个 advice,不管它有没有返回值,但是必须要方法内部,调用一下
pjp.proceed();
否则方法将不会会被执行,从而也导致了@Before
这个 advice 不会被触发。