概述
前一讲中,我们一步一步分析到了AbstractAutoProxyCreator抽象类的postProcessBeforeInstantiation()方法中,其实,我们也知道现在调用的其实是AnnotationAwareAspectJAutoProxyCreator类的postProcessBeforeInstantiation()方法。
这一讲中,我们就来看看AnnotationAwareAspectJAutoProxyCreator作为后置处理器,它的postProcessBeforeInstantiation()方法都做了些什么。
AnnotationAwareAspectJAutoProxyCreator后置处理器作用
bean创建之前调用postProcessBeforeInstantiation()方法
AnnotationAwareAspectJAutoProxyCreator作为后置处理器,它其中的一个作用就是在每一个bean创建之前,调用其postProcessBeforeInstantiation()方法。
当创建MathCalculator的实例时,如下所示。
先来判断当前bean是否在advisedBeans中
advisedBeans是一个Map集合,里面保存了所有需要增强的bean名称。哪些是需要增强的bean呢?就是一些业务逻辑类,例如MathCalculator,因为它里面的方法需要切面来切的,所以执行它里面的方法,不能简单的调用执行,需要增强一下(代理),这些就是需要增强的bean。
再来判断当前bean是否是基础类型,或者是否是切面(标注了@Aspect注解的)
基础类型就是当前bean是否是实现了Advice、Pointcut、Advisor以及AopInfrastructureBean这些接口。我们可以点进去isInfrastructureClass()方法里面大概看一看,如下图所示。
除了判断当前bean是否是基础类型之外还会判断当前bean是否是标注了@Aspect注解的切面。
很显然,当前的这个bean(即MathCalculator)既不是基础类型,也不是标注了@Aspect注解的切面。
最后判断是否需要跳过
所谓的跳过,就是说不要再处理这个bean了。那跳过又是怎么判断的呢?
可以看到,它会在这儿执行一堆的业务逻辑,首先是调用findCandidateAdvisors()方法找到候选的增强器的集合。
检查candidateAdvisors变量,可以看到现在有4个增强器,什么叫增强器啊?增强器就是切面里面的那些通知方法。 而且第一个增强器就是logStart()方法,如下图所示。
总结:在shouldSkip()方法里面,首先会获取到以上这4个通知方法。也就是说,先来获取候选的增强器。所谓的增强器其实就是切面里面的那些通知方法,只不过,在这儿是把通知方法的详细信息包装成了一个Advisor,并将其存放在了一个List集合中,即增强器的集合,即是说,每一个通知方法都会被认为是一个增强器。
一直运行回postProcessBeforeInstantiation()方法中,这时,我们可以知道,if判断语句中的第二个表达式的值就是false。
此刻,是要调用calculator()方法来创建MathCalculator对象了。
可以发现当我们把MathCalculator对象创建完了以后,在这儿又会调用postProcessAfterInitialization()方法。
其实,上面我也已经说过了,在每次创建bean的时候,都会先调用postProcessBeforeInstantiation()方法,然后再调用postProcessAfterInitialization()方法。
创建完对象以后,调用postProcessAfterInitialization()方法
前面我就已说过,AnnotationAwareAspectJAutoProxyCreator作为后置处理器,它的第一个作用。现在,我就来说说它的第二个作用,即在创建完对象以后,会调用其postProcessAfterInitialization()方法。
我们调用刚才的calculator()方法创建完MathCalculator对象以后,发现又会调用AnnotationAwareAspectJAutoProxyCreator(后置处理器)的postProcessAfterInitialization()方法。
我们重点要关注的内容其实是那个叫wrapIfNecessary的方法。
什么情况是需要包装的呢?我们可以按下F5快捷键进入该方法里面去看一看,如下图所示。
们重点要关注的内容其实是下面这个叫getAdvicesAndAdvisorsForBean的方法。
从该方法上面的注释中可以得知,它是用于创建代理对象的,从该方法的名称上(见名知义),我们也可以知道它是来获取当前bean的通知方法以及那些增强器的。
获取当前bean的所有增强器
调用getAdvicesAndAdvisorsForBean()方法获取当前bean的所有增强器,也就是那些通知方法,最终封装成这样一个Object[] specificInterceptors数组。
程序会运行回wrapIfNecessary()方法。
现在这个叫specificInterceptors的Object[]数组里面已经具有了那些指定好的增强器,这些增强器其实就是要拦截目标方法执行的。
小结
以上这一小节的流程,我们可以归纳为:
- 找到候选的所有增强器,也就是说是来找哪些通知方法是需要切入到当前bean的目标方法中的
- 获取到能在当前bean中使用的增强器
- 给增强器排序
保存当前bean在advisedBeans中,表示这个当前bean已经被增强处理了
当程序运行到下面这一行代码时,就会将当前bean添加到名为advisedBeans的Map集合中,表示这个当前bean已经被增强处理了。
当程序继续往下运行时,会发现有一个createProxy()方法,这个方法非常重要,它是来创建代理对象的。
下面我们主要来研究一下createProxy()方法。
若当前bean需要增强,则创建当前bean的代理对象
当程序运行到createProxy()方法处时,就会创建当前bean的代理对象,那么这个代理对象怎么创建的呢?
运行到457这行代码处,可以看到是先拿到所有增强器,然后再把这些增强器保存到代理工厂(即proxyFactory)中。
直至运行到createProxy()方法的最后一行,如下图所示。
这行代码的意思是说,利用代理工厂帮我们创建一个代理对象。
那到底是怎么来创建创建AOP代理的呢?
进入createAopProxy()方法中去看一看,如下图所示,这时Spring会自动决定,是为组件创建jdk的动态代理呢,还是为组件创建cglib的动态代理?
也就是说,会在这儿为组件创建代理对象,并且有两种形式的代理对象,它们分别是:
- 一种是JdkDynamicAopProxy这种形式的,即jdk的动态代理
- 一种是ObjenesisCglibAopProxy这种形式的,即cglib的动态代理
那么Spring是怎么自动决定是要创建jdk的动态代理,还是要创建cglib的动态代理呢?如果当前类是有实现接口的,那么就使用jdk来创建动态代理,如果当前类没有实现接口,例如MathCalculator类,此时jdk是没法创建动态代理的,那么自然就得使用cglib来创建动态代理了。而且,咱们可以让Spring强制使用cglib,关于这一点,后续如果有机会的话,那么我们再来探讨。
很显然,现在是使用cglib来创建动态代理的。
一直让程序运行回wrapIfNecessary()方法中,如下图所示,这时createProxy()方法返回的proxy对象是一个通过Spring cglib增强了的代理对象。
一直让程序运行到applyBeanPostProcessorsAfterInitialization()方法中,如下图所示。
至此,刚才的那个wrapIfNecessary()方法就完全算是调用完了。
经过上面的分析,我们知道,wrapIfNecessary()方法调用完之后,最终会给容器中返回当前组件使用cglib增强了的代理对象。
对于MathCalculator这个组件来说,以后从容器中获取到的就是该组件的代理对象,然后在执行其目标方法时,这个代理对象就会执行切面里面的通知方法。
小结
以上这一小节的流程,我们可以归纳为:
- 获取所有增强器,所谓的增强器就是切面里面的那些通知方法。
- 然后再把这些增强器保存到代理工厂(即proxyFactory)中。
- 为当前组件创建代理对象,并且会有两种形式的代理对象,它们分别如下,最终Spring会自动决定,是为当前组件创建jdk的动态代理,还是创建cglib的动态代理。
- 一种是JdkDynamicAopProxy这种形式的,即jdk的动态代理
- 一种是ObjenesisCglibAopProxy这种形式的,即cglib的动态代理
参考
Spring注解驱动开发第30讲——AnnotationAwareAspectJAutoProxyCreator作为后置处理器,你知道它都做了些什么吗?
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/99982.html