Spring AOP源碼

AOP是什么怎么用就不在這里贅述了,這里就從源碼看一下AOP的實(shí)現(xiàn)启妹。

1、Spring 如果要支持注解形式的AOP,就要在配置文件中配置<aop:aspectj-autoproxy/>啄清。

這里簡(jiǎn)單說(shuō)一下Spring解析標(biāo)簽的過(guò)程:Spring中將標(biāo)簽分為默認(rèn)標(biāo)簽(import、alias,bean和beans)和自定義標(biāo)簽俺孙。

<aop:aspectj-autoproxy/>屬于自定義標(biāo)簽盒延,解析過(guò)程為當(dāng)讀取到這個(gè)標(biāo)簽時(shí),會(huì)根據(jù)命名空間去找到對(duì)應(yīng)的自定義標(biāo)簽處理器AopNamespaceHandler鼠冕,AopNamespaceHandler會(huì)執(zhí)行init()方法添寺。在這里會(huì)將AspectJAutoProxyBeanDefinitionParser進(jìn)行注冊(cè)。而AspectJAutoProxyBeanDefinitionParser正是專門解析"aspectj-autoproxy"標(biāo)簽的解析器懈费。

1

AspectJAutoProxyBeanDefinitionParser實(shí)現(xiàn)了BeanDefinitionParser接口计露,會(huì)執(zhí)行parse()對(duì)標(biāo)簽進(jìn)行解析。這個(gè)parse()中AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element)這個(gè)方法憎乙,從名字就可以看出是用來(lái)注冊(cè)自動(dòng)代理創(chuàng)建器票罐,我們具體看下這個(gè)方法內(nèi)做了什么。

2

一共做了三件事:

????1)注冊(cè)或者升級(jí)AnnotationAwareAspectJAutoProxyCreator

? ? 2)對(duì)于proxy-target-class以及expose-proxy 屬性的處理

? ? 3)注冊(cè)組件并通知泞边,便于監(jiān)聽(tīng)器做進(jìn)一步處理

3

1)注冊(cè)或者升級(jí)AnnotationAwareAspectJAutoProxyCreator

? ?先看第一件该押,跟蹤代碼可依次走到如下兩個(gè)方法。主要功能點(diǎn)就是注冊(cè)AnnotationAwareAspectJAutoProxyCreator阵谚。

? ?具體注冊(cè)過(guò)程蚕礼,會(huì)先判斷自動(dòng)代理創(chuàng)建器是否已經(jīng)存在。

????? ? 1)不存在梢什,直接創(chuàng)建新的創(chuàng)建器奠蹬。

????? ? 2)若存在

? ? ? ????? ? ? 1)且與想要?jiǎng)?chuàng)建的新創(chuàng)建器相同,不進(jìn)行操作嗡午。

? ? ? ????? ? ? 2)且與想要?jiǎng)?chuàng)建的新創(chuàng)建器不同囤躁,就要判斷兩個(gè)創(chuàng)建器的優(yōu)先級(jí),如果新創(chuàng)建器優(yōu)先級(jí)高,則進(jìn)行新創(chuàng)建器的創(chuàng)建狸演,否則不操作還是用原來(lái)創(chuàng)建器言蛇。

4
5

?2)對(duì)于proxy-target-class以及expose-proxy 屬性的處理

? ? ?這個(gè)方法實(shí)際就是讀取配置文件并將屬性賦值的過(guò)程。


6

????????說(shuō)一下這個(gè)兩個(gè)屬性作用宵距。

?????? ????1)proxy-target-class

? ? ? ? ????默認(rèn)情況下猜极,"proxy-target-class"默認(rèn)是"false",當(dāng)被代理類實(shí)現(xiàn)了至少一個(gè)接口消玄,Spring默認(rèn)使用JDK動(dòng)態(tài)代理跟伏,當(dāng)被代理類沒(méi)有實(shí)現(xiàn)接口時(shí)使用CGLIB代理,但是如果想強(qiáng)制任何時(shí)候都使用CGLIB代理翩瓜,那么需要如下配置:

????????????????????????????????<aop : aspectj-autoproxy????proxy-target-class="true"/>

? ? ? ? ????2)expose-proxy

? ? ? ? ?如下例子可以說(shuō)明這個(gè)屬性受扳。


有時(shí)候目標(biāo)對(duì)象內(nèi)部的自我調(diào)用將無(wú)法實(shí)施切面中的增強(qiáng),此處的this 指向目標(biāo)對(duì)象兔跌,因此調(diào)用this.b()將不會(huì)執(zhí)行b事務(wù)切面勘高,即不會(huì)執(zhí)行事務(wù)增強(qiáng)。

為了解決這個(gè)問(wèn)題坟桅,配置:

<aop:aspectj-autoproxy expose-proxy=”true”/>

然后將以上代碼中的“this.b()”修改為“ ((AService) AopContext.currentProxy()).b()”即可华望。

通過(guò)以上的修改便可以完成對(duì)a和b方法的同時(shí)增強(qiáng)。


?3)注冊(cè)組件并通知仅乓,便于監(jiān)聽(tīng)器做進(jìn)一步處理

? ? 這一步是注冊(cè)組件赖舟,對(duì)于AOP實(shí)現(xiàn)沒(méi)有什么關(guān)聯(lián)。



2夸楣、在上面完成了AnnotationAwareAspectJAutoProxyCreator的注冊(cè)創(chuàng)建宾抓,這個(gè)類也是實(shí)現(xiàn)AOP的關(guān)鍵,我們看這個(gè)類到底怎么實(shí)現(xiàn)的AOP豫喧∈矗可以看到AnnotationAwareAspectJAutoProxyCreator類實(shí)現(xiàn)了BeanPostProcessor接口。

BeanPostProcessor常常被稱為后置處理器紧显,作用是在Bean對(duì)象在實(shí)例化和依賴注入完畢后讲衫,在顯示調(diào)用初始化方法的前后添加我們自己的邏輯。流程如下:

Spring IOC容器實(shí)例化Bean--->調(diào)用BeanPostProcessor的postProcessBeforeInitialization方法--->調(diào)用bean實(shí)例的初始化方法--->調(diào)用BeanPostProcessor的postProcessAfterInitialization方法


AnnotationAwareAspectJAutoProxyCreator實(shí)現(xiàn)BeanPostProcessor 后孵班,當(dāng)Spring加載Bean時(shí)會(huì)在初始化后調(diào)用其父類AbstractAutoProxyCreator重寫的postProcessAfterInitialization方法涉兽,對(duì)生產(chǎn)出的bean進(jìn)行包裝。

7

具體看下AbstractAutoProxyCreator重寫的postProcessAfterInitialization方法重父,其中wrapIfNecessary()方法是我們要關(guān)注的花椭。

8

看注釋相信大家也大概明白這個(gè)方法的邏輯了,無(wú)非是先判斷這個(gè)類是不是需要增強(qiáng)房午,如果需要增強(qiáng)就創(chuàng)建代理。這里我們主要看getAdvicesAndAdvisorsForBean()和createProxy()這兩個(gè)方法丹允。

9


1)getAdvicesAndAdvisorsForBean()


10

下面實(shí)際做了兩件事郭厌,獲取所有的增強(qiáng)器以及尋找所有增強(qiáng)器中適用于這個(gè)bean 的增強(qiáng)器袋倔。


11

我們先來(lái)看一下怎么獲取的所有增強(qiáng)器。主要是分別獲取了xml配置中的增強(qiáng)器和注解中的增強(qiáng)器折柠。

12

我們主要看一下怎樣獲取注解形式的增強(qiáng)器宾娜,也就是buildAspectJAdvisors()這個(gè)方法,圖片里有注釋扇售,簡(jiǎn)單來(lái)說(shuō)就是拿到所有beanName前塔,遍歷beanName找到有@Aspect注解的類,然后處理這些有@Aspect注解的類的提取增強(qiáng)器承冰。

13

提取增強(qiáng)器主要是getAdvisors()這個(gè)方法华弓,我們接下來(lái)看下這個(gè)方法具體實(shí)現(xiàn)。

1)getPointcut()拿到切點(diǎn)信息

2)new InstantiationModelAwarePointcutAdvisorImpl()封裝生成增強(qiáng)器困乒。

14

1)getPointcut()拿到切點(diǎn)信息

切點(diǎn)信息獲取其實(shí)也是獲取方法上注解的信息寂屏,不詳細(xì)解釋了。

15

2)new InstantiationModelAwarePointcutAdvisorImpl()封裝生成增強(qiáng)器娜搂。

可以看出來(lái)如果是懶加載迁霎,則先看到這可能還是不能看出來(lái)我們熟悉的內(nèi)容,別急百宇,往下看考廉,看instantiateAdvice()方法。

16

我們可以看到before携御、after這些我們熟悉的切面注解了芝此,spring會(huì)根據(jù)注解生成不同類型的增強(qiáng)器,常說(shuō)的前置增強(qiáng)因痛、后置增強(qiáng)婚苹、環(huán)繞增強(qiáng)。

17

至此我么我們知道了spring怎么獲取所有的增強(qiáng)器鸵膏。那么返回之前我們的地方膊升。拿到所有增強(qiáng)器后,就是找出適用這個(gè)bean的增強(qiáng)器谭企,其實(shí)就是找到符合我們配置的通配符的增強(qiáng)器廓译。

18

至此我們分析完了獲取這個(gè)類增強(qiáng)器的方法。如果這個(gè)類存在需要增強(qiáng)器债查,就要?jiǎng)?chuàng)建代理非区,也就是createProxy()。

19

這個(gè)方法就為我們創(chuàng)建了代理類,當(dāng)實(shí)際調(diào)用時(shí)是代理類替代目標(biāo)類為我們執(zhí)行了方法盹廷,當(dāng)然就把我們的切面方法也執(zhí)行了征绸。

20

















BeanPostProcessor

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子管怠,更是在濱河造成了極大的恐慌淆衷,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渤弛,死亡現(xiàn)場(chǎng)離奇詭異祝拯,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)她肯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門佳头,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人晴氨,你說(shuō)我怎么就攤上這事康嘉。” “怎么了瑞筐?”我有些...
    開(kāi)封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵凄鼻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我聚假,道長(zhǎng)块蚌,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任膘格,我火速辦了婚禮峭范,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘪贱。我一直安慰自己纱控,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布菜秦。 她就那樣靜靜地躺著甜害,像睡著了一般。 火紅的嫁衣襯著肌膚如雪球昨。 梳的紋絲不亂的頭發(fā)上尔店,一...
    開(kāi)封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音主慰,去河邊找鬼嚣州。 笑死,一個(gè)胖子當(dāng)著我的面吹牛共螺,可吹牛的內(nèi)容都是我干的该肴。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼藐不,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼匀哄!你這毒婦竟也來(lái)了秦效?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拱雏,失蹤者是張志新(化名)和其女友劉穎棉安,沒(méi)想到半個(gè)月后底扳,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體铸抑,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年衷模,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鹊汛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡阱冶,死狀恐怖刁憋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情木蹬,我是刑警寧澤至耻,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站镊叁,受9級(jí)特大地震影響尘颓,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜晦譬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一疤苹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧敛腌,春花似錦卧土、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至生棍,卻和暖如春颤霎,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背足绅。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工捷绑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人氢妈。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓粹污,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親首量。 傳聞我的和親對(duì)象是個(gè)殘疾皇子壮吩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

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

  • 0.AOP整體流程 1)@EnableAspectJAutoProxy 開(kāi)啟AOP功能2)@EnableAspec...
    王偵閱讀 1,870評(píng)論 0 1
  • 轉(zhuǎn)自:https://javadoop.com/post/spring-aop-source 之前寫過(guò) IOC 的...
    劍書藏于西閱讀 1,305評(píng)論 0 2
  • 前言 最近看了《從零開(kāi)始寫JavaWeb框架》进苍,想比較一下Spring AOP的實(shí)現(xiàn)方式和書的上實(shí)現(xiàn)方式有什么不同...
    未知海苔閱讀 3,635評(píng)論 3 5
  • 面向方面編程(AOP)補(bǔ)充了面向?qū)ο缶幊?OOP),提供了另一種思考程序結(jié)構(gòu)的方式鸭叙。OOP中模塊化的關(guān)鍵單元是類觉啊,...
    Kohler閱讀 338評(píng)論 0 0
  • AOP 面向切面編程,相對(duì)于OOP面向?qū)ο缶幊獭?Spring AOP存在的目的是為了解耦沈贝。AOP可以讓一組類共享...
    xiaolyuh閱讀 495評(píng)論 1 2