【Spring源碼】22.AOP之代理對象的創(chuàng)建

前言

上一章我們講了 , 在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)建代理對象的具體過程邢享。

image

進入createProxy方法鹏往,可以看到會把 beanClass,beanName,以及命中的Advisor集合,以及原生bean 包裝成SingletonTargetSource對象傳進去

image

1. proxyFactory對象的創(chuàng)建

createProxy方法會先常見一個ProxyFactory代理工廠對象骇塘,并且從AbstractAutoProxyCreator對象伊履,復(fù)制一些屬性進去

image
image

1.1. 判斷接口與更改proxyTargetClass屬性值

這里最重要的屬性是proxyTargetClass,將參與 決定使用jdk動態(tài)代理,還是cglib代理款违。

就是@EnableAspectJAutoProxy注解里的 proxyTargetClass 屬性

@Component
@EnableAspectJAutoProxy(proxyTargetClass = false)
public class AopConfig {
}

如果是默認的false(默認),那么接下來會有一個判斷的過程唐瀑,有可能會被spring改成true

image

evaluateProxyInterfaces方法會去判斷 該beanClass 是否有實現(xiàn)接口

先是取出 beanClass 實現(xiàn)的所有接口

image

然后遍歷,遍歷的過程中會判斷 接口的合法性

image
  1. isConfigurationCallbackInterface判斷接口得不是 InitializingBean/ DisposableBean / Closeable/ AutoCloseable/ Aware 這幾個接口插爹,這是spring提供的接口
image
  1. isInternalLanguageInterface 判斷 哄辣!( 接口名稱.equals("groovy.lang.GroovyObject") ||接口名稱.getName().endsWith(".cglib.proxy.Factory") || 接口名稱.endsWith(".bytebuddy.MockAccess"));)
image

這兩個判斷都 符合的話请梢,hasReasonableProxyInterface變量會變成true, 并退出遍歷

hasReasonableProxyInterface 為true的話, proxyTargetClass配置就還是false,不變

否則為false, 則會被 更改成 true

image

1.2 proxyFactory其他屬性賦值

判斷完 ProxyTargetClass 屬性后,對TargetSource 目標(biāo)對象力穗,advisor對象集合等屬性進行賦值

image

2. 創(chuàng)建aop代理對象-AopProxy對象

proxyFactory對象 創(chuàng)建成功后毅弧,開始創(chuàng)建AopProxy對象

image

這個AopProxy對象啊,是spring的aop代理對象当窗,它兩個實現(xiàn)類

  1. 通過jdk動態(tài)代理實現(xiàn)的aop代理對象
  2. 通過cglib代理實現(xiàn)的aop代理對象

通過它可以創(chuàng)建jdk動態(tài)代理/cglib 代理對象

看createAopProxy(classLoader)方法

image

調(diào)用aop代理工廠對象 創(chuàng)建aop代理對象 : createAopProxy

這里注意够坐,會傳入 proxyFactory對象, proxyFactory對象是持有原生bean和該類匹配的所有切面對象的

image

這里就有判斷 具體是使用jdk動態(tài)代理還是cglib了

image

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對象

來看下 是怎么生成代理對象的

代碼回到這

image

進入JdkDynamicAopProxy類的 getProxy方法

image

這里就是 按照jdk動態(tài)代理 的 模式 創(chuàng)建代理對象了疏遏,傳入類加載器,實現(xiàn)的所有正常接口救军,InvocationHandler對象财异,創(chuàng)建代理對象

這里值得注意的是傳入的 InvocationHandler對象就是 JdkDynamicAopProxy對象

那么JdkDynamicAopProxy 肯定實現(xiàn)了InvocationHandler接口,那么肯定會實現(xiàn)invoke方法唱遭,具體的增強邏輯 就在invoke方法里了戳寸。

image

并且他的AdvisedSupport advised 屬性是 proxyFactory{

            advisors :所有的切面,

            targetSource:被代理目標(biāo)對象

            proxyTargetClass :代理的方式

}

當(dāng)方法執(zhí)行的時候就會執(zhí)行 InvokeHandle的invoke方法,取出AdvisedSupport advised屬性里的advisors進行方法級別的匹配拷泽,并調(diào)用advice疫鹊,進行增強。

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末司致,一起剝皮案震驚了整個濱河市拆吆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌脂矫,老刑警劉巖枣耀,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異庭再,居然都是意外死亡捞奕,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進店門拄轻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來颅围,“玉大人,你說我怎么就攤上這事恨搓≡捍伲” “怎么了?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長一疯。 經(jīng)常有香客問我撼玄,道長,這世上最難降的妖魔是什么墩邀? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任票罐,我火速辦了婚禮,結(jié)果婚禮上铜犬,老公的妹妹穿的比我還像新娘灼芭。我一直安慰自己,他們只是感情好竹海,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布慕蔚。 她就那樣靜靜地躺著,像睡著了一般斋配。 火紅的嫁衣襯著肌膚如雪孔飒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天艰争,我揣著相機與錄音坏瞄,去河邊找鬼。 笑死甩卓,一個胖子當(dāng)著我的面吹牛鸠匀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逾柿,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼缀棍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了机错?” 一聲冷哼從身側(cè)響起爬范,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弱匪,沒想到半個月后坦敌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡痢法,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年狱窘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片财搁。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡蘸炸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出尖奔,到底是詐尸還是另有隱情搭儒,我是刑警寧澤穷当,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站淹禾,受9級特大地震影響馁菜,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜铃岔,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一汪疮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧毁习,春花似錦智嚷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至载碌,卻和暖如春猜嘱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嫁艇。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工泉坐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人裳仆。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像孤钦,于是被迫代替她去往敵國和親歧斟。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

推薦閱讀更多精彩內(nèi)容