序
从我学Spring AOP开始,我就一直有一个问题,Spring到底是如何使实现动态代理的?它到底是如何创建动态代理对象的?于是便有了这篇文章。
想了解AOP简单执行流程的jym,可以参考我的这篇文章:Spring Aop 到底做了什么? 后续我也会补上AOP执行流程详细源码分析。
前置知识
Spring中创建代理的三种场景:
1.最标准的就是bean初始化以后创建动态代理对象。
也就是在AbstractAutoProxyCreator
类中
postProcessAfterInitialization
方法。
2.三级缓存中创建代理对象,也可以说是循环依赖需要依赖代理对象。
我的这篇文章中也有提及Spring 循环依赖解析
也就是在SmartInstantiationAwareBeanPostProcessor
接口中getEarlyBeanReference
方法。
而AbstractAutoProxyCreator
类继承了SmartInstantiationAwareBeanPostProcessor
接口。
3.实例化
之前创建代理对象,注意是实例化
而不是初始化
。
如果不清楚什么是实例化还是初始化可以参考我的这篇文章Spring bean 的生命周期问题
也就是在AbstractAutowireCapableBeanFactory
类中的createBean
方法中的resolveBeforeInstantiation
方法。
源码分析
本文中就以最常见的bean初始化以后做动态代理
来做源码分析。由于涉及到的类方法对象等实在太多,
所以下面的解析尽可能的都在图片之中,这样效果可能会好些。
注:我的springboot版本
是2.4.3
,若根据图片跟踪源码请注意。版本不同可能有所差异,但是大致思路不会有错。
入口方法wrapIfNecessary
下面就来分析最为重要的两个方法:
1.准备代理bean对应的切面getAdvicesAndAdvisorsForBean
方法。
2.创建代理对象createProxy
方法。
getAdvicesAndAdvisorsForBean 为增强bean找出它的切面
由于为代理bean准备切面的方法里面内容依旧很多,所以我也只会挑最重要的地方讲,尽量把大致的框架列出来让jym有个整体的了解,知道重要方法中做了什么。重要的细节也会补上。
根据上图我们来逐一分析各个方法
findCandidateAdvisors 找出所有的切面
主要的方法在 AnnotationAwareAspectJAutoProxyCreator
子类中
这个方法中为每个@AspectJ切面的每个方法都创造了一个Spring的通知对象,具体的创建过程就在这个方法的
synchronized
代码块中,由于不是本文讨论重点,这里就不做分析了,有兴趣的jy可以自行去阅读。
findAdvisorsThatCanApply 在所有切面中找出自己的切面
至于canApply方法本文就不做详细分析了,里面大致就是通过pointcut,判断你的表达式(比如execution
表达式等)是否和你的bean匹配,从而判断这个切面是不是符合bean的切面。
extendAdvisors 在通知链最前面加上一个暴露调用的通知
sortAdvisors 切面排序
总结和问题
通过上述一系列操作,找出了符合条件的增强bean的切面,且对切面都做了order层面的排序。
但是切面本来就是有自己的顺序的,比如before在最前面,after在最后面,那这些切面的排序到底是在哪里 就已经排好了呢?spring中是否有他们的默认排序?
答案当然是有的,其实在创建切面的时候spring就对切面做好了排序,还记得上面提到在 buildAspectJAdvisors
方法中的synchroized
关键词中创建切面对应的spring通知么?
createProxy 创建代理对象
buildAdvisors 创建通知链条
getProxy 获取代理
createAopProxy 创建AOP代理
getPorxy 真正的获取代理的实际对象
如果是jdk代理,直接定位到JdkDynamicAopProxy
类的getProxy
方法
非常好理解,就是用Proxy
的newProxyInstance
方法来创建动态代理对象。
如果是cglib动态代理,直接定位到ObjenesisCglibAopProxy
类的getProxy
方法,也就是CglibAopProxy
的getProxy
方法。
在这个方法中会去调用cglib真正的创建cglib动态代理对象。
由于笔者水平有限,对于cglib不是很了解,这部分代码真的无力详细解读,但是还是要讲一下自己的思路和几个关键点。
首先看到入参是enhancer
和callbacks
。
上图是我在百度上随意找的一张图,但是它很好的解释了enhancer就是创建代理的核心类,而callback就是回调接口。也就是说cglib代理对象执行增强方法时会使用到callback。
直接定位到getCallbacks
方法
总结
创建动态代理这一块大致思路非常简单,但是细节依然很多,如果要深入了解还需自行阅读源码。
尾
非常感谢能看到这里的jym。本文其实并不难理解,顺着思路应该可以明白个大概,细节部分自己也可以去阅读源码。如果有错误的地方还望各位不吝指教。