Spring AOP 动态代理源码解析

(基于spring aop 5.3.1)

前述、spring aop 主要解析类为AnnotationAwareAspectJAutoProxyCreator

主要的动态代理逻辑是在在AbstractAutoProxyCreator类的三个方法中,这三个方法分别是:

(1)org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#getEarlyBeanReference

(2)org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

(3)org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessBeforeInstantiation

一、getEarlyBeanReference方法

(1)如果aop切入点表达是匹配的的bean处于循环依赖中,然后这个bean在创建过程中被提前暴露使用,

那么在提前暴露过程中,最终会调用这lambda表达式获取提前暴露的bean实例,最终调用的是getEarlyBeanReference方法

(2)getEarlyBeanReference这个方法内会调用所有SmartInstantiationAwareBeanPostProcessor类型的后置处理器的getEarlyBeanReference方法(这方法名字直译过来意思其实就很明显嘛)

(3)根据SmartInstantiationAwareBeanPostProcessor的继承树:

解析@Aspect、@Pointcut等注解的AnnotationAwareAspectJAutoProxyCreator是继承自SmartInstantiationAwareBeanPostProcessor。

而AnnotationAwareAspectJAutoProxyCreator也通过实现getEarlyBeanReference方法对提前暴露的bean(前提是匹配切入点表达式)进行代理处理。

(4)AnnotationAwareAspectJAutoProxyCreator本身其实也没有实现getEarlyBeanReference方法,具体实现逻辑是在父类AbstractAutoProxyCreator的getEarlyBeanReference方法中。

getEarlyBeanReference又是通过wrapIfNecessary方法,wrapIfNecessary方法才是真正实现了代理逻辑

wrapIfNecessary的逻辑大概是:(截图在小总结那里)

判断这个bean是否被代理过,如果有,则直接返回传进来的,避免创建多个代理对象。

如果没有被代理过,则创建代理对象,记录到缓存中,然后返回代理对象。

 

二、postProcessAfterInitialization方法(bean初始化后调用)

(1)该方法调用时机是在调用bean初始化方法之后,doCreateBean -> initializeBean 中

(2)初始化后调用的方法如下,内部其实也是循环调用后置处理器的postProcessAfterInitialization方法,

最终会调用到aop的后置处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization,对bean创建代理对象,然后返回代理对象。

AnnotationAwareAspectJAutoProxyCreator本身也没有实现postProcessAfterInitialization,

也是像getEarlyBeanReference方法一样,实现逻辑在父类AbstractAutoProxyCreator。

看过前面的,这里应该对wrapIfNecessary这个有印象吧,AbstractAutoProxyCreator的postProcessAfterInitializa也是使用wrapIfNecessary创建代理。

 

三、wrapIfNecessary,真正创建代理的方法

getEarlyBeanReference和postProcessAfterInitializa这两个最终都是调用wrapIfNecessary创建代理对象。

逻辑大概:

判断这个bean是否被代理过,如果有,则直接返回传进来的,避免创建多个代理对象。

如果没有被代理过,则创建代理对象,记录到缓存中,然后返回代理对象。

 

四、postProcessBeforeInstantiation(bean初始化前调用)

(1)这个和前面两个稍微有点不同,前两个最终都是通过wrapIfNecessary创建代理,并且前两个都是在spring bean创建的生命周期中对目标bean进行包装代理。

也就是说目标bean其实还是走完了spring bean自身的创建流程的,只不过最终是返回了代理对象被spring 容器管理。

而当前这个,调用时机是在创建bean之前(这个时候bean还没有进入spring的创建流程,连实例对象都还没有创建),并且如果返回的bean不为空,那就不走spring 创建bean的流程了。

 

(2)postProcessBeforeInstantiation由resolveBeforeInstantiation调用。

调用链是resolveBeforeInstantiation -> applyBeanPostProcessorsBeforeInstantiation -> postProcessBeforeInstantiation

(3)某个后置处理器如果通过postProcessBeforeInstantiation返回的bean不为null,那这个bean的创建流程就需要这个后置处理器自己实现(属性填充、初始化、注入等等),spring不会去管这个bean的创建了。

(4)接下来再回到AbstractAutoProxyCreator的postProcessBeforeInstantiation方法,其实和wrapIfNecessary方法写的基本一样(如下图)

区别就在于,postProcessBeforeInstantiation会判断是否有CustomTargetSource,如果有,则使用自定义的TargetSource创建bean实例(目标对象),然后再创建代理对象

(5)自定义TargetSource,需要实现TargetSourceCreator,这是AOP留出来的一个扩展接口。

实现这个接口,就可以不用spring创建流程去创建bean,而是自己实现创建目标bean的逻辑。

其实把上面那张图的注释翻译一下就是:

如果我们有自定义的TargetSource,请在此处(指的是当前这个postProcessBeforeInstantiation方法)创建代理。

抑制目标Bean的不必要的默认实例化(不通过spring去创建):TargetSource将以自定义方式处理目标实例(自己实现创建bean的流程,属性填充、初始化等)

再放一个AOP对TargetSourceCreator接口的一个实现:

 

 

五,到此,解析写完结束,源码多看多读,发现越来越容易理解了

 

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值