前言
上一章我們講了 , 在AbstractAutoProxyCreator類實現(xiàn)至BeanPostProcessor接口的postProcessAfterInitialization方法中灵妨,在遍歷每一個正在實例化的bean時广鳍,會先解析容器類所有的beanNames對應(yīng)的class,來創(chuàng)建并收集advisor對象这敬。 并且會把當(dāng)前beanClass 與 advisor對象集合進行匹配展辞,如果匹配到了advisor對象,那么就說明 這個bean的某些方法時需要增強的铅鲤,那么就會通過jdk動態(tài)代理或者cglib 來創(chuàng)建代理對象划提,實現(xiàn)aop。
接下來看看spring aop創(chuàng)建代理對象的具體過程邢享。
進入createProxy方法鹏往,可以看到會把 beanClass,beanName,以及命中的Advisor集合,以及原生bean 包裝成SingletonTargetSource對象傳進去
1. proxyFactory對象的創(chuàng)建
createProxy方法會先常見一個ProxyFactory代理工廠對象骇塘,并且從AbstractAutoProxyCreator對象伊履,復(fù)制一些屬性進去
1.1. 判斷接口與更改proxyTargetClass屬性值
這里最重要的屬性是proxyTargetClass,將參與 決定使用jdk動態(tài)代理,還是cglib代理款违。
就是@EnableAspectJAutoProxy注解里的 proxyTargetClass 屬性
@Component
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class AopConfig {
}
如果是默認的false(默認),那么接下來會有一個判斷的過程唐瀑,有可能會被spring改成true
evaluateProxyInterfaces方法會去判斷 該beanClass 是否有實現(xiàn)接口
先是取出 beanClass 實現(xiàn)的所有接口
然后遍歷,遍歷的過程中會判斷 接口的合法性
- isConfigurationCallbackInterface判斷接口得不是 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 這幾個接口插爹,這是spring提供的接口
- isInternalLanguageInterface 判斷 哄辣!( 接口名稱.equals("groovy.lang.GroovyObject") ||接口名稱.getName().endsWith(".cglib.proxy.Factory") || 接口名稱.endsWith(".bytebuddy.MockAccess"));)
這兩個判斷都 符合的話请梢,hasReasonableProxyInterface變量會變成true, 并退出遍歷
hasReasonableProxyInterface 為true的話, proxyTargetClass配置就還是false,不變
否則為false, 則會被 更改成 true
1.2 proxyFactory其他屬性賦值
判斷完 ProxyTargetClass 屬性后,對TargetSource 目標(biāo)對象力穗,advisor對象集合等屬性進行賦值
2. 創(chuàng)建aop代理對象-AopProxy對象
proxyFactory對象 創(chuàng)建成功后毅弧,開始創(chuàng)建AopProxy對象
這個AopProxy對象啊,是spring的aop代理對象当窗,它兩個實現(xiàn)類
- 通過jdk動態(tài)代理實現(xiàn)的aop代理對象
- 通過cglib代理實現(xiàn)的aop代理對象
通過它可以創(chuàng)建jdk動態(tài)代理/cglib 代理對象
看createAopProxy(classLoader)方法
調(diào)用aop代理工廠對象 創(chuàng)建aop代理對象 : createAopProxy
這里注意够坐,會傳入 proxyFactory對象, proxyFactory對象是持有原生bean和該類匹配的所有切面對象的
這里就有判斷 具體是使用jdk動態(tài)代理還是cglib了
if ( 如果ProxyTargetClass配置的為true,
或者該類沒有除 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 以外的接口-->ProxyTargetClass會被改成true,
或者 (如果 沒有任何接口 或者 只實現(xiàn)了SpringProxy ){
if(該類 是否是接口,或者是 Proxy類型(該class就是jdk動態(tài)代理創(chuàng)建的))
那么還是會使用jdk動態(tài)代理
Else{
使用cglib
}
}else{
使用jdk動態(tài)代理
}
如何還要考慮是否代理崖面,是否只實現(xiàn)SpringProxy接口 那樣太復(fù)雜了 元咙,下面這個歸納一下就可以滿足常用的情況了
proxyTargetClass=false(默認)
被代理類是否實現(xiàn)除 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 以外的接口:
是 jdk動態(tài)代理
否 proxyTargetClass會被改成true
proxyTargetClass=true
被代理類是否是接口||是否是代理類(一般無法滿足)
是 : jdk動態(tài)代理
否 : cglib動態(tài)代理
不管是返回JdkDynamicAopProxy 還是 ObjenesisCglibAopProxy,都會傳入 proxyFactory對象巫员,在構(gòu)造方法賦值給JdkDynamicAopProxy的 AdvisedSupport advised屬性蛾坯。
也就是 JdkDynamicAopProxy {
AdvisedSupport advised = proxyFactory{
advisors :所有的切面,
targetSource:被代理目標(biāo)對象
proxyTargetClass :代理的方式
}
}
3. AopProxy對象創(chuàng)建jdk代理對象
如果是jdk動態(tài)代理,上面返回的是JdkDynamicAopProxy對象
來看下 是怎么生成代理對象的
代碼回到這
進入JdkDynamicAopProxy類的 getProxy方法
這里就是 按照jdk動態(tài)代理 的 模式 創(chuàng)建代理對象了疏遏,傳入類加載器,實現(xiàn)的所有正常接口救军,InvocationHandler對象财异,創(chuàng)建代理對象
這里值得注意的是傳入的 InvocationHandler對象就是 JdkDynamicAopProxy對象
那么JdkDynamicAopProxy 肯定實現(xiàn)了InvocationHandler接口,那么肯定會實現(xiàn)invoke方法唱遭,具體的增強邏輯 就在invoke方法里了戳寸。
并且他的AdvisedSupport advised 屬性是 proxyFactory{
advisors :所有的切面,
targetSource:被代理目標(biāo)對象
proxyTargetClass :代理的方式
}
當(dāng)方法執(zhí)行的時候就會執(zhí)行 InvokeHandle的invoke方法,取出AdvisedSupport advised屬性里的advisors進行方法級別的匹配拷泽,并調(diào)用advice疫鹊,進行增強。