Spring AOP通知的执行顺序模型分析与代码验证

这篇博客的目的是要理清Spring AOP中各种通知的执行顺序,主要是同一切面内和不同切面内通知的执行顺序区别,以及如何在切面级别上更改顺序。关于Spring AOP的整体实现思路请参考----源码分析-Spring AOP是如何实现的?(一)

同一切面内的不同通知的执行顺序

在同一个切面内的通知,它们的执行顺序是 Around - Before - After - After Returning / After Throwing。具体的通知执行模型如下。
在这里插入图片描述

  1. 首先会先执行环绕通知,环绕通知内由于我们会调用proceed方法去调用目标方法,所以这里可以认为执行的是环绕通知proceed方法前的逻辑。
  2. 其次调用proceed方法后,就会执行前置通知。
  3. 前置通知后就会执行原目标对象的方法。
  4. 目标方法执行后,会根据执行情况判断,如果没有异常,则回到环绕通知内,执行proceed方法后的逻辑。
  5. 环绕通知执行后,准备执行后置通知。
  6. 后置通知正常执行,则准备执行最终通知。
  7. 若第四步目标方法抛出异常,则直接执行后置通知,然后执行异常通知。

这里源码层次的执行策略可以参考上一篇博客 — Spring AOP的通知执行策略

好,用我们之前的代码测试一下结果。

在这里插入图片描述

同一切面内的相同通知的执行顺序

同一切面内,两个相同类型的通知,它们的顺序是无法预测的,这里不再过多说明。

不同切面的通知执行顺序

多个切面的通知作用于一个目标方法,这里我们可以认为对一个目标类方法进行多次代理。
它的通知执行模型如下。
在这里插入图片描述

如上图,如果要指定切面的优先级,只需要在此切面上添加@Order注解,设置的数值越小,优先级越大。第一次看可能会很混乱,只要记住切面先进后出,就可以了。如果不指定切面优先级,则执行顺序是由Spring AOP解析切面的顺序来为准则,这个顺序是无法预测的。

创建两个切面,切点为同一个方法,试一试结果。

在这里插入图片描述
我们再修改代码,在目标方法内抛出一个异常,在测试一下结果。

在这里插入图片描述
日志看起来有点乱,但勉强也可以看出,通知执行的顺序和我们的模型一致。

通知内抛出异常,剩余通知的执行顺序

在我们平时写代码调试过程中,不一定所有的异常都是在目标方法内产生,很多时候,我们的通知的逻辑很复杂,异常也很有可能从这里抛出,如果有这种情况,通知的执行顺序会有什么改变么?

答案程序会短路剩余的通知,直接执行对应切面的后置通知和异常通知。

看一看具体的执行模型。下图是两个切面,优先级高的切面内的环绕通知内抛出异常,这个节点,还没有执行JoinPoint的proceed方法,结果就是程序无法执行后续切面,且无法执行目标方法,直接执行此切面的后置通知和异常通知。

在这里插入图片描述
模拟此节点异常,看一看具体执行情况。

@Around("pointCut()")
	public Object adviceAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		log.info("advice : order = 1 ---->>>> Around Start");
		if (1 > 0) {
			throw new Exception("exception");
		}
		Object result = proceedingJoinPoint.proceed();
		log.info("advice : order = 1 ---->>>> Around End");
		return result;
	}

执行结果如下图。

在这里插入图片描述
同理,如果异常节点发生在优先级低的切面内的通知,比如说发生在执行模型内 Order为2的切面内的before方法,那结果就是目标方法不执行,但会执行此切面的后置通知和异常通知,以及Order为1切面的后置通知和异常通知。

执行结果如下。

在这里插入图片描述
好了,关于Spring AOP的通知执行顺序基本就是这些内容,有遗漏或有疑问的地方请在留言区说明,我后续再补充。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值