知识储备:详解Spring中AOP原理(基于注解版)3

接着上一篇博客讲,上一篇博客地址:https://blog.csdn.net/qq_36625757/article/details/83658735

11.前面已经创建了MathCal的代理对象了,我们在调用方法时加一个断点

《知识储备:详解Spring中AOP原理(基于注解版)3》

这里返回的确实是代理对象,这个对象中保存了详细信息(增强器,原始对象等),我们进入bean.add(2, 10);中,来到org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept(Object, Method, Object[], MethodProxy)方法,拦截目标方法的执行。

《知识储备:详解Spring中AOP原理(基于注解版)3》

根据ProxyFactory获得目标方法的拦截器链,如果没有拦截器链,就直接执行目标方法。

《知识储备:详解Spring中AOP原理(基于注解版)3》

 如果有拦截器链,将需要执行的目标对象,目标方法,连接器链传入,创建一个CglibMethodInvocation对象并调用proceed()方法

《知识储备:详解Spring中AOP原理(基于注解版)3》

那么拦截器链如何获取呢?我们进入this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);方法中

《知识储备:详解Spring中AOP原理(基于注解版)3》

通过advisorChainFactory获得目标方法的拦截器链,进入this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this, method, targetClass);

《知识储备:详解Spring中AOP原理(基于注解版)3》

先创建一个list保存所有拦截器,可以看到,list创建时,已经初始化长度,这个长度就是通知方法的个数+一个默认通知,对于本案例就是5个。之后又在循环遍历所有增强器,调用registry.getInterceptors(advisor);将其包装为Interceptor[],那么是如何包装的呢?

《知识储备:详解Spring中AOP原理(基于注解版)3》

进入到其中查看,其实很简单,首先判断增强器是不是MethodInterceptor,如果是就直接加入到list中,如果不是就使用增强器的适配器AdvisorAdapter将增强器转为MethodInterceptor,之后转为数组返回。foreach循环完后就获得了拦截器链(每一个通知方法又被包装为拦截器,利用MethodInterceptor机制)。

12.获得了拦截器链,拦截器链是如何执行的呢?获得拦截器链后有new了一个CglibMethodInvocation并调用了proceed()方法

《知识储备:详解Spring中AOP原理(基于注解版)3》

我们进入到proceed()方法

《知识储备:详解Spring中AOP原理(基于注解版)3》

this.currentInterceptorIndex表示执行的拦截器索引默认等于-1,首先判断是否有拦截器执行目标方法,或者拦截器索引等于拦截器数组大小减一相等(也就是执行到最后一个拦截器)都会执行目标方法。下面我们debug调试,查看拦截器的执行。

首先来到第一个拦截器

《知识储备:详解Spring中AOP原理(基于注解版)3》

拦截器索引等于-1,拦截器数组等于4.通过this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);获得到第一个拦截器,拦截器索引+1,执行interceptorOrInterceptionAdvice).invoke(this);方法,传入的this为ChlibProxy

《知识储备:详解Spring中AOP原理(基于注解版)3》

进入其中

《知识储备:详解Spring中AOP原理(基于注解版)3》

《知识储备:详解Spring中AOP原理(基于注解版)3》

其中invocation是当前线程共享的MethodInvocation,先从其中获得MethodInvocation,再将ChlibProxy加入到当前线程公享数据中,调用ChlibProxy的procees()方法,进入mi.proceed()中,又来到我们之前的proceed()方发,初始的拦截器索引+1了

《知识储备:详解Spring中AOP原理(基于注解版)3》

然后又重this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);获得第二个拦截器

《知识储备:详解Spring中AOP原理(基于注解版)3》

之后又会调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);来到AspectJAfterThrowingAdvice的invoke()方法中

《知识储备:详解Spring中AOP原理(基于注解版)3》

有是调用mi.proceed()方法,又来到proceed()方法,拦截器索引+1,又获的一个拦截器

《知识储备:详解Spring中AOP原理(基于注解版)3》

AfterReturningAdviceInterceptor这个拦截器还是调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);方法,进入其中

《知识储备:详解Spring中AOP原理(基于注解版)3》

又调用mi.proceed();方法,来到proceed();,拦截器索引+1,获得一个拦截器

《知识储备:详解Spring中AOP原理(基于注解版)3》

又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);方法,进入其中

《知识储备:详解Spring中AOP原理(基于注解版)3》

又调用mi.proceed();来到proceed()方法,拦截器索引+1,获得一个拦截器

《知识储备:详解Spring中AOP原理(基于注解版)3》

又调用((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);方法,进入其中

《知识储备:详解Spring中AOP原理(基于注解版)3》

这里就调用了前置通知,之后又调用mi.proceed();来到proceed()方法

《知识储备:详解Spring中AOP原理(基于注解版)3》

此时拦截器索引为4,等于拦截器数组大小4,就调用invokeJoinpoint();方法,执行目标方法并返回,之后就调用后置通知

《知识储备:详解Spring中AOP原理(基于注解版)3》

 

 

《知识储备:详解Spring中AOP原理(基于注解版)3》

后置通知调用完毕如果有异常就将异常向上抛,执行异常通知

《知识储备:详解Spring中AOP原理(基于注解版)3》

如果没有异常,就执行返回通知

《知识储备:详解Spring中AOP原理(基于注解版)3》

返回通知执行完毕,程序也就跑完了。拦截器链就是链式或去拦截器,调用拦截器的invoke()方法,每一个拦截器都等待下一个拦截器执行完毕返回以后,在执行。通过拦截器链的机制,保证通知方法与目标方法的执行顺序。

13.拦截器链调用过程

《知识储备:详解Spring中AOP原理(基于注解版)3》

14.总结

我们使用@EnableAspectJAutoProxy开启AOP功能,主要是@EnableAspectJAutoProxy会给容器中注册一个AnnotationAwareAspectJAutoProxyCreator后置处理器,通过AnnotationAwareAspectJAutoProxyCreator注册后置处理,在这一步会创建AnnotationAwareAspectJAutoProxyCreator,然后通过finishBeanFactoryInitialization(beanFactory);初始化剩下的单实例bean,我们自己的类就会创建出来,AnnotationAwareAspectJAutoProxyCreator也会拦截组件的创建过程,在组件创建后,AnnotationAwareAspectJAutoProxyCreator会通过postProcessBeforeInstantiation()判断主键是否需要包装,如果需要,就会将切面中的通知方法包装为增强器(Advisor),然后给目标对象创建一个代理对象,接下来就是通过代理对象执行目标方法。代理对象执行目标方法前会被CglibProxy.intercept()拦截,拦截中,先得到目标方法的拦截器链(增强器包装为拦截器),通过拦截器链机制,依次进入每一个拦截器进行执行。

执行方式一(目标方法没有出现异常):前置通知->目标方法->后置通知->返回通知

执行方式二(目标方法出现异常):前置通知->目标方法->后置通知->异常通知

 

    原文作者:AOP
    原文地址: https://blog.csdn.net/qq_36625757/article/details/83715140
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞