Spring基础系列--AOP织入逻辑跟踪

  原创作品,可以转载,但是请标注出处地址:

  首先我们通过CglibAopProxy类的intercept方法构建一个方法调用,并执行其proceed方法:

  然后进入ReflectiveMethodInvocation类的proceed()方法,由于currentInterceptorIndex下标从-1开始,在进行++自增操作之后变成0,获取interceptorsAndDynamicMethodMatchers中的第一个拦截器。

  我们看下interceptorsAndDynamicMethodMatchers中的内容:

 

  第一个是ExposeInvocationInterceptor,这个正是之前在

  然后进入到ExposeInvocationInterceptor方法的invoke方法中

  在这个方法中我们可以看到,90行处,将方法调用mi放到了invocation中。那invocation是什么呢?如下

  可见,是将方法调用保存到了ThreadLocal中,这个invocation保存的正是当前AOP的方法调用。

  然后执行mi.proceed()方法,这就是一个递归调用了。在这里执行proceed方法,将会继续执行下一个通知,执行逻辑又回到ReflectiveMethodInvocation类的proceed()方法,这时currentInterceptorIndex自增之后为1,正好指向interceptorsAndDynamicMethodMatchers中的下一个通知:

  很显然,下一个通知为后置异常通知afterThrowingTest。

  执行这个通知的invoke方法,代码调到AspectJAfterThrowingAdvice类的invoke方法。

  在异常通知的invoke方法中直接递归调用proceed方法,并将剩下所有的调用执行全部try...catch住,在最后catch块中执行其通知逻辑。

  除开普通的拦截器之外,最先执行的通知是异常通知,它会将剩下所有的调用逻辑全部catch住,也就是说在这期间发生的任何异常都会被捕捉到,而且一旦哪一步发生了异常,那么执行就会被中断,到这里执行catch逻辑。

  这下又回到了ReflectiveMethodInvocation类的proceed方法。currentInterceptorIndex再次自增为2,指向通知链中第三个通知:

  后置返回通知,遵从以上的逻辑我们看看下一步的行为:

  在AfterReturningAdviceInterceptor类中

  果然去执行后置返回通知的invoke方法去啦,第一步任然是递归调用,又回到了ReflectiveMethodInvocation类的proceed方法去执行第四个通知:

 这个是后置终点通知,这个通知有点特殊哦,我们来看看其invoke方法

  它也是先直接进行递归调用,将其逻辑放在最后,这个是真正的最后,直接放到了finally块中,这表示什么,这表示,无论接下来的调用操作是否会发生异常,这部分逻辑永远会执行。

  现在又一次回去了ReflectiveMethodInvocation类的proceed方法去执行第五个通知:

  嗯,这次是环绕通知,这个通知不同于其他通知,其他通知只执行于方法的一点,这个通知却需要执行于方法的两处。所以它会拥有一个ProceedJoinPoint参数,这个参数就是用来区分这两处执行逻辑的:目标方法之前与之后。

  直接执行到最后一句,首次要执行invokeAdviceMethod方法了:

  然后执行invokeAdviceMethodWithGivenArgs方法:

  它要直接执行通知方法中的逻辑,想想为什么没有在进行递归调用而是直接执行的通知方法呢?

  因为环绕通知将递归调用挪移到了通知逻辑中,由程序员自定义执行,来看看我自定义的环绕通知逻辑:

  我们先不考虑具体的逻辑,先看看大体结构,显示一段逻辑,然后执行jp.proceed(os)方法。然后又是一段逻辑。所谓的环绕就是将逻辑围绕在目标执行前后。

  通知的内容真正开始执行了,这里首先执行了环绕通知的前置部分。

  我们执行递归调用之后,我们发现逻辑跑到了MethodInvocationProceedingJoinPoint中,这是啥类呢?

  这竟然是ProceedJoinPoint的实现类,我们执行jp.proceed(os)方法当然会跑到这里了,

  其实ProceedJoinPoint的proceed方法有两个重载,一个有参数,一个无参数,分别用于针对目标方法有参数和目标发无参数的情况,所以这里这两个方法其实逻辑类似,只是有参数的方法会针对参数进行一番操作,将参数设置到方法调用中,这么做,新的方法参数会替换就的方法参数,这也是我们可以在环绕通知中修改参数的原理所在。

50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信