Spring AOP源码分析十一

上节我们分析了拦截器ExposeInvocationInterceptor和AspectJAfterThrowingAdvice的核心逻辑,我们现在知道,其实拦截器的核心逻辑,就是不断的递归调用ReflectiveMethodInvocation,而通过每个拦截器中的递归调用,就可以将这些拦截器连成一根链条。同时每个拦截器中还会实现自己的一些增强逻辑,比如ExposeInvocationInterceptor拦截器实现了同线程共用拦截器链的功能,而AspectJAfterThrowingAdvice拦截器在有异常的时候,会来调用执行AfterThrowing增强方法。我们也知道,aspectJ一共有5种增强,那其他的增强,是不是也会不断的递归调用ReflectiveMethodInvocation呢?其他的增强又是怎么实现它自己的增强逻辑的?我们这节就接着来分析一下。上节我们分析到了拦截器AfterReturningAdviceInterceptor,那我们接着来看下吧,拦截器代码如下:
在这里插入图片描述
通过上边的代码,我们可以看到,其实这里还是通过mi.proceed()这行代码递归调用了ReflectiveMethodInvocation。并且我们还可以看到,这里是没有try catch处理的,而是在方法mi.proceed()正常返回之后,会执行this.advice.afterReturning()方法。
那么如果执行mi.proceed()方法发生了异常,此时就不会执行afterReturning()方法了,而只有正常执行结束时,才会来执行AfterReturning增强逻辑。那AfterReturning增强具体是怎么执行的呢?我们来进一步看下afterReturning()方法,代码如下:
在这里插入图片描述
可以看到,执行AfterReturning增强其实是通过invokeAdviceMethod()方法完成的。而invokeAdviceMethod()方法的代码,之前我们已经分析过了,具体的代码如下:
在这里插入图片描述
在这里插入图片描述
通过上图,我们可以看到,其实invokeAdviceMethod()方法主要是通过调用invokeAdviceMethodWithGivenArgs()方法完成功能的,而invokeAdviceMethodWithGivenArgs()方法中关键的其实就一行代码,那就是this.aspectJAdviceMethod.invoke()这行代码
说白了就是通过反射调用了增强方法,而这个aspectJAdviceMethod我们上节讲过了,aspectJAdviceMethod其实就是切面中定义的增强方法,在这里其实就是AfterReturning增强方法。接下来,我们来看下拦截器链中的拦截器,这样就可以知道,下个该执行的拦截器是谁了,如下图:
在这里插入图片描述
通过上图,我们可以看到,此时拦截器链下标currentInterceptorIndex经过++操作后已经变为3了,所以下边会来获取并执行下标为3的拦截器,也就是AspectJAfterAdvice拦截器。我们用一张流程图来表示:
在这里插入图片描述
通过上图,可以看到,都是先递归调用ReflectiveMethodInvocation,等递归调用完成后再执行AfterReturning增强,而这次递归调用的拦截器,其实就是AspectJAfterAdvice拦截器了。接下来就轮到执行AspectJAfterAdvice拦截器了,AspectJAfterAdvice代码如下:
在这里插入图片描述
上边的代码还是递归调用ReflectiveMethodInvocation,需要注意的是,这里是一个try finally语句,而在finally语句块中,调用了invokeAdviceMethod()方法,而这个方法的代码,说白了就是通过反射来调用对应的增强方法,在这里,其实就是调用在切面中定义的After增强方法。由于执行的方法在finally中所以无论是否有异常,After增强都会执行,因为After增强的本质就是一个finally语句块!我们来看下一个要执行的拦截器是哪个,如下图:
在这里插入图片描述
通过上图,我们可以看到,此时拦截器链下标currentInterceptorIndex通过++操作后值变为4,因此接下来就会来获取并执行下标为4的拦截器,也就是AspectJAroundAdvice拦截器了,也就是说,下一个要执行的拦截器是AspectJAroundAdvice拦截器了。我们用一张流程图来表示:
在这里插入图片描述
这里还是不停的在递归调用ReflectiveMethodInvocation,以此来达到不断的调用下一个拦截器的效果。接下来,我们就要来分析AspectJAroundAdvice拦截器了,到目前为止,我们切面中定义的增强方法全都没有执行,我们接着往下分析,此时AspectJAroundAdvice的代码如下:
在这里插入图片描述
通过上图,可以看到,这里已经没有递归调用ReflectiveMethodInvocation了,而是直接通过invokeAdviceMethod()方法调用了Around增强方法。而这个invokeAdviceMethod()方法我们上边也分析很多遍了,其实就是通过反射的方式,调用了切面中定义的增强方法,而这里调用的就是切面中定义的Around增强方法,其实就是下边这个方法,如下图:
在这里插入图片描述
通过上图,我们可以看到,此时就会来执行我们日志切面中定义的Around增强方法了,首先就是执行Around前置增强逻辑,就是输出了一行信息。接着就会执行Object proceed = point.proceed()这行代码,那这个 point.proceed()是干嘛的呢?我们可以来看下 point.proceed()中的代码,如下图:
在这里插入图片描述
我们可以看到,上边的图中其实就一行代码,那就是this.methodInvocation.invocableClone().proceed(),通过这行代码,我们知道,最终还是调用了一个proceed()方法,关键就是this.methodInvocation.invocableClone()的执行结果到底是那个对象。我们来看下这个this.methodInvocation.invocableClone()的运行结果就可以了,如下图
在这里插入图片描述
通过上图,我们可以看到,其实this.methodInvocation.invocableClone()这行代码的运行结果,就是ReflectiveMethodInvocation类的一个实例,那也就是说this.methodInvocation.invocableClone().proceed()这行代码本质,还是递归调用了ReflectiveMethodInvocation类的proceed()方法。我们回到主线,再来看下Around增强的代码,如下图:
在这里插入图片描述
也就是说,Around增强方法在执行时,会首先执行point.proceed()完前边的代码,也就是Around前置增强,接着就会使用point.proceed()递归调用ReflectiveMethodInvocation类的proceed(),等递归返回执行结果后,才会执行Around后置增强。
那么这次递归该执行哪个拦截器了呢?我们来看下:在这里插入图片描述通过上图,我们可以看到,拦截器链下标currentInterceptorIndex进行++操作后值为5,因此接下来会获取并执行下标为5的拦截器,也就是MethodBeforeAdviceInterceptor拦截器了。我们用一张流程图来表示:
在这里插入图片描述
可以看到,AspectJAroundAdvice拦截器先执行了Around前置增强,也就是输出了一行信息,接着递归调用了ReflectiveMethodInvocation,从而会来执行拦截器MethodBeforeAdviceInterceptor。那接下来我们就来看下MethodBeforeAdviceInterceptor拦截器的代码吧,如下图:
在这里插入图片描述
通过上图,可以看到,这里首先会执行Before增强方法,然后接着会通过mi.proceed()递归调用ReflectiveMethodInvocation,那Before增强方法是怎么执行的呢?我们再进一步看下before()方法的代码,如下图:
在这里插入图片描述
可以看到,其实上边这个before()方法,也是通过调用invokeAdviceMethod()方法完成的,而这个invokeAdviceMethod()方法我们知道,它就是通过反射,直接调用了切面中定义的增强方法。before()方法执行完毕后,接着就会递归调用ReflectiveMethodInvocation了,此时就又回到这个proceed()方法了,如下图:
在这里插入图片描述
这个时候,就又开始一步一步执行上边这个proceed()方法了,此时就会来执行上图红框中的if判断了。此时这个currentInterceptorIndex变量经过一次又一次的++操作后,现在已经变为5了,我们看下边这张图:
在这里插入图片描述
在这里插入图片描述
通过上边的图,可以看到,此时currentInterceptorIndex变量已经累加到5了,而拦截器链中一共有6个拦截器,那么拦截器的size-1的结果就为5,那此时上图中的if条件就会成立。说白了就是this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1这行代码会返回true,接下来就会执行return invokeJoinpoint()这行代码
而invokeJoinpoint()这个方法,我们在之前分析过,它其实就是用于调用目标方法的,代码如下:
在这里插入图片描述
在这里插入图片描述
通过上边的图可以看到,其实就是通过反射来调用了目标方法。到目前为止,拦截器链就全部执行一遍了,总结为一张图的话,就像下边这样:
在这里插入图片描述
我们来简单总结一下,到这里为止都执行了哪些增强。其实通过上边的图,我们可以看到,首先是在AspectJAroundAdvice拦截器中执行了Around前置增强,然后接着在MethodBeforeAdviceInterceptor拦截器中执行了Before增强。
非常关键的一点是,在MethodBeforeAdviceInterceptor拦截器递归调用ReflectiveMethodInvocation的proceed()方法时,发现这个时候,递归结束条件成立了,此时就会执行目标方法。所以,目前为止的执行流程是这样的:Around前置增强 -> Before增强 -> 目标方法。但现在有个问题就是,除了Around前置增强和Before增强外,其余的增强还都是没有执行的状态!
那么什么时候会执行其他增强方法呢?之前是不断的递归调用ReflectiveMethodInvocation的proceed()方法,而此时满足了递归结束的条件,那么此时在递归的过程中,调用的方法就会层层返回,这样其他的增强就会得到执行了。
说白了就是下边这张图的效果,如下:

在这里插入图片描述
通过上图,大家可以看到,在满足递归结束的条件后,首先会执行目标方法,而执行完目标方法后,接着就会层层返回执行结果,接着其他的拦截器就会分别执行自己内部的增强方法了。通过上图,我们可以总结出aspectJ五种增强的执行顺序,如下:
1、Around前置增强(AspectJAroundAdvice负责处理)
2、Before增强(MethodBeforeAdviceInterceptor负责处理)
3、目标方法
4、Around后置增强(AspectJAroundAdvice负责处理)
5、After增强(AspectJAfterAdvice负责处理,无论是否有异常,都会执行)
6、AfterReturning增强(AfterReturningAdviceInterceptor负责处理,没有异常时,才会执行)
7、AfterThrowing增强(AspectJAfterThrowingAdvice负责处理,有异常时,才会执行)
其中需要注意的是,AfterReturning增强和AfterThrowing增强不会同时执行,而是只会执行其中一个。可以看到,其实每一种拦截器都单独处理了一种增强,比如MethodBeforeAdviceInterceptor拦截器就是用来处理Before增强的,而AspectJAfterAdvice拦截器就是用来处理After增强的。

一张图来梳理下AOP代理的执行流程:
在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

youngerone123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值