Spring注解驱动之AnnotationAwareAspectJAutoProxyCreator的作用

概述

前一讲中,我们一步一步分析到了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作为后置处理器,你知道它都做了些什么吗?

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

融极

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

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

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

打赏作者

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

抵扣说明:

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

余额充值