25.spring源码之AOP
上篇文章提到了AOP的入口,今天接着上篇文章来谈谈AOP,spring的AOP是一个BeanPostProcessor的应用。@Aspect注解切面的解析以下图为例

1.AbstractAutowireCapableBeanFactory类的initializeBean()方法


2.进入applyBeanPostProcessorsAfterInitialization()方法

那么AOP的入口类是什么时候生成的加载到Spring容器的呢,无非就是通过xml配置文件方式或者注解,看注解的方式,注解是通过@EnableAspectJAutoProxy,我们看看这个注解

这个注解通过@Import导入的AspectJAutoProxyRegistrar.class

进入该方法

在下面这个方法中完成了AOP入口类的注册

3.进入postProcessAfterInitialization()方法

4.进入wrapIfNecessary()方法

5.调用getAdivcesAndAdvisorsForBean()方法获取当前bean的所有切面

进入findElinglibleAdvisors()方法

5.1调用findCandidateAdvisors()获取所有的切面

先看父类的findCandidateAdvisors()方法,在看看buildAspectJAdvisors()方法,

进入findAdvisorBeans()方法

再看buildAspectJAdvisors()方法


进入getAdvisors()方法

先看getAdvisorMethods(),这个方法是获取所有增强的方法如@Around、@Before、@After、@AfterReturing、@AfterThrowing这些注解的方法,同时进行排序

再看getAdvisor()方法获取切面,这是在一个循环里面,每一个增强方法与切点都会组成一个切面

5.1.1getPointcut()获取PointCut对象

进入findAspectJAnnotationMethod()方法,

进入findAnnotation()方法

进入AspectJAnnotation

5.1.2创建Advisor切面对象,并返回

构造方法中给Pointcut赋值、同时还需要advice增强

进入instantiateAdvice()方法

进入getAdvice()方法,根据不同的注解创建不同类型的Advice对象,并返回



5.2在回到5中indElinglibleAdvisors()方法,进入5.2

在5.1的findCandidateAdvisors()方法中已经获取到了所有的切面,每个切面中都有一个Advice和一个PointCut,而这个PointCut的expression的值是增强方法注解的值,现在进入5.2findAdvisorsThatCanApply(),从所有的切面中获取作用在当前beanClass的切面

进入findAdvisotsThatCanApply()方法

每一个Pointcut都有一个ClassFilter和MethodMatch,在ClassFilter和MethodMatch中分别都有一个match()方法,去进行类和方法的匹配,进入canApply()方法

进入canApply()方法

进入match()方法

5.3在回到5中indElinglibleAdvisors()方法,进入5.3

通过5.1和5.2已经筛选出符合要求的切面,现在看5.3extendAdvisors()方法

进入该方法,如果存在@Aspect注解生成的切面,就会创建一个默认的切面

该切面有什么作用,看他得Invoke方法就知道了

该切面就是把MethodInvocation对象放入ThreadLocal中,并调用proceed()方法火炬传递给下一个切面
6.在5中获取到了所有作用在当前beanClass上面的切面,现在回到4中的方法

调用createProxy()方法创建代理对象


6.1进入buildAdvisors()方法

进入resolveInterceptorNames()方法

一开始interceptorNames是为空的,我们可以自定义一个Advice,然后把这个Advice的name复制给AOP入口类对象的interceptorNames属性,就会把这个Advice封装成一个Advisors,我们可以通过BeanPostProcessor来完成
自定义Advice

自定义BeanPostProcessor,这里是一个BeanPostProcessor的应用,AOP入口的也需要实例化,那么在Bean的实例化中就会走到AOP入口那个方法,而那个方法就是一个BeanPostProcessor的应用,就会调用我们自定义的这个BeanPostProcessor,而我们这个自定的BeanPostProcessor就是把AOP入口类实例化的时候把这个Advice的name赋值给它的interceptorNames,那么当其他类有切面走AOP入口的时候,AOP入口类中interceptorNames就不为空了,于是就会生成一个全局的Advisors。

6.2getProxy()方法创建代理对象

先看createAopProxy()方法,这里会判断是JDK动态代理还是Cglib代理

再看gerProxy()方法,以JDK动态代理为例
.
第三个参数this就是JdkDynamicAopProxy对象,一个实现了是实现了InvocationHandler接口的类的实例,代理对象生成后,把代理对象返回了。可以得知,在bean的实例化过程中,如果该bean是有相关的切面,返回的是代理对象。
我们知道,通过代理对象调用方法,就是调用实现了InvocationHandler接口类的对象的invoke方法,这里就是JdkDynamicAopProxy对象,我们看它的invoke方法。
7.方法调用



7.1该方法获取所有匹配的MethodInterceptor也就是advice,也可能有MethodMatch

进入方法


7.2执行链为空,说明没有方法需要被增强,直接使用被代理对象调用方法

7.3执行链不为空,进行链式调用


这里会根据不同类型的advice完成对应类型的方法调用,@Before注解的方法,则是进入MethodBeforeAdviceInterceptor类的invoke()方法

当所有的增强方法都调用完,就会调用invokeJoinpoint()方法完成被代理对象方法的调用。
8.自定义Advisor

创建advice,MethodInterceptor继承于Advice接口,invoke()方法的参数是一个MethodInvocation对象,通过这个对象进行火炬传递

创建Pointcut,每个Pointcut都有一个ClassFilter,MethodMatch,这里class的match直接返回true,然后有一个方法的匹配是判断方法上是否有@EasyCache注解,有才返回true,因为我们重写了isRunTime()方法,并且返回了true,那么还会调用三个参数的match()方法,这个方法可以匹配到参数级别,我们的条件是eat方法的参数值是Jack才匹配返回true,才走增强。


创建advisor,Advisor有一个Pointcut和Advice

被代理对象类

测试

浙公网安备 33010602011771号