面向切面編程AOP

AOP知識(shí)整理


AOP(Aspect-Oriented Programming):面向切面的編程成肘。OOP(Object-Oriented Programming)面向?qū)ο蟮木幊檀懒铡?duì)于OOP我們已經(jīng)再熟悉不過了,對(duì)于AOP沦疾,可能我們會(huì)覺得是一種新特性侵蒙,其實(shí)AOP是對(duì)OOP的一種補(bǔ)充造虎,OOP面向的是縱向編程,繼承纷闺、封裝算凿、多態(tài)是其三大特性份蝴,而AOP是面向橫向的編程。


面向切面編程(AOP)通過提供另外一種思考程序結(jié)構(gòu)的途經(jīng)來彌補(bǔ)面向?qū)ο缶幊蹋∣OP)的不足澎媒。在OOP中模塊化的關(guān)鍵單元是類(classes)搞乏,而在AOP中模塊化的單元?jiǎng)t是切面。切面能對(duì)關(guān)注點(diǎn)進(jìn)行模塊化戒努,例如橫切多個(gè)類型和對(duì)象的事務(wù)管理请敦。


AOP框架是Spring的一個(gè)重要組成部分。但是Spring IoC容器并不依賴于AOP储玫,這意味著你有權(quán)利選擇是否使用AOP侍筛,AOP做為Spring IoC容器的一個(gè)補(bǔ)充,使它成為一個(gè)強(qiáng)大的中間件解決方案。


AOP在Spring Framework中的作用


  • 提供聲明式企業(yè)服務(wù)撒穷,特別是為了替代EJB聲明式服務(wù)匣椰。最重要的服務(wù)是聲明性事務(wù)管理(這個(gè)我想是AOP使用最多的一處了)。


  • 允許用戶實(shí)現(xiàn)自定義切面端礼,用AOP來完善OOP的使用禽笑。


  • 1. AOP概念:


    學(xué)習(xí)AOP,當(dāng)然得先了解一下其眾多的概念性術(shù)語:


  • 切面(Aspect):一個(gè)關(guān)注點(diǎn)的模塊化蛤奥,這個(gè)關(guān)注點(diǎn)可能會(huì)橫切多個(gè)對(duì)象佳镜。事務(wù)管理是J2EE應(yīng)用中一個(gè)關(guān)于橫切關(guān)注點(diǎn)的很好的例子。在Spring AOP中凡桥,切面可以使用基于模式)或者基于@Aspect注解的方式來實(shí)現(xiàn)蟀伸。


  • 連接點(diǎn)(Joinpoint):在程序執(zhí)行過程中某個(gè)特定的點(diǎn),比如某方法調(diào)用的時(shí)候或者處理異常的時(shí)候缅刽。在Spring AOP中啊掏,一個(gè)連接點(diǎn)總是表示一個(gè)方法的執(zhí)行。


  • 通知(Advice):在切面的某個(gè)特定的連接點(diǎn)上執(zhí)行的動(dòng)作衰猛。其中包括了“around”迟蜜、“before”和“after”等不同類型的通知(通知的類型將在后面部分進(jìn)行討論)。許多AOP框架(包括Spring)都是以攔截器做通知模型啡省,并維護(hù)一個(gè)以連接點(diǎn)為中心的攔截器鏈娜睛。


  • 切入點(diǎn)(Pointcut):匹配連接點(diǎn)的斷言。通知和一個(gè)切入點(diǎn)表達(dá)式關(guān)聯(lián)冕杠,并在滿足這個(gè)切入點(diǎn)的連接點(diǎn)上運(yùn)行(例如,當(dāng)執(zhí)行某個(gè)特定名稱的方法時(shí))酸茴。切入點(diǎn)表達(dá)式如何和連接點(diǎn)匹配是AOP的核心:Spring缺省使用AspectJ切入點(diǎn)語法分预。


  • 引入(Introduction):用來給一個(gè)類型聲明額外的方法或?qū)傩裕ㄒ脖环Q為連接類型聲明(inter-type declaration))。Spring允許引入新的接口(以及一個(gè)對(duì)應(yīng)的實(shí)現(xiàn))到任何被代理的對(duì)象薪捍。例如笼痹,你可以使用引入來使一個(gè)bean實(shí)現(xiàn)IsModified接口配喳,以便簡(jiǎn)化緩存機(jī)制。


  • 目標(biāo)對(duì)象(Target Object): 被一個(gè)或者多個(gè)切面所通知的對(duì)象凳干。也被稱做被通知(advised)對(duì)象晴裹。 既然Spring AOP是通過運(yùn)行時(shí)代理實(shí)現(xiàn)的,這個(gè)對(duì)象永遠(yuǎn)是一個(gè)被代理(proxied)對(duì)象救赐。


  • AOP代理(AOP Proxy):AOP框架創(chuàng)建的對(duì)象涧团,用來實(shí)現(xiàn)切面契約(例如通知方法執(zhí)行等等)。在Spring中经磅,AOP代理可以是JDK動(dòng)態(tài)代理或者CGLIB代理泌绣。


  • 織入(Weaving):把切面連接到其它的應(yīng)用程序類型或者對(duì)象上,并創(chuàng)建一個(gè)被通知的對(duì)象预厌。這些可以在編譯時(shí)(例如使用AspectJ編譯器)阿迈,類加載時(shí)和運(yùn)行時(shí)完成。Spring和其他純Java AOP框架一樣轧叽,在運(yùn)行時(shí)完成織入苗沧。


  • 通知類型:


  • 前置通知(Before advice):在某連接點(diǎn)之前執(zhí)行的通知,但這個(gè)通知不能阻止連接點(diǎn)之前的執(zhí)行流程(除非它拋出一個(gè)異常)炭晒。


  • 后置通知(After returning advice):在某連接點(diǎn)正常完成后執(zhí)行的通知:例如待逞,一個(gè)方法沒有拋出任何異常,正常返回腰埂。


  • 異常通知(After throwing advice):在方法拋出異常退出時(shí)執(zhí)行的通知飒焦。


  • 最終通知(After (finally) advice):當(dāng)某連接點(diǎn)退出的時(shí)候執(zhí)行的通知(不論是正常返回還是異常退出)。


  • 環(huán)繞通知(Around Advice):包圍一個(gè)連接點(diǎn)的通知屿笼,如方法調(diào)用牺荠。這是最強(qiáng)大的一種通知類型。環(huán)繞通知可以在方法調(diào)用前后完成自定義的行為驴一。它也會(huì)選擇是否繼續(xù)執(zhí)行連接點(diǎn)或直接返回它自己的返回值或拋出異常來結(jié)束執(zhí)行休雌。


  • 環(huán)繞通知是最常用的通知類型。和AspectJ一樣肝断,Spring提供所有類型的通知杈曲,我們推薦你使用盡可能簡(jiǎn)單的通知類型來實(shí)現(xiàn)需要的功能。例如胸懈,如果你只是需要一個(gè)方法的返回值來更新緩存担扑,最好使用后置通知而不是環(huán)繞通知,盡管環(huán)繞通知也能完成同樣的事情趣钱。用最合適的通知類型可以使得編程模型變得簡(jiǎn)單涌献,并且能夠避免很多潛在的錯(cuò)誤。比如首有,你不需要在JoinPoint上調(diào)用用于環(huán)繞通知的proceed()方法燕垃,就不會(huì)有調(diào)用的問題枢劝。


    在這里,基于@AspectJ的AOP我就不多寫了卜壕,因?yàn)槲腋嗖A于Spring中使用ProxyFactoryBean創(chuàng)建AOP代理您旁。


    2.使用ProxyFactoryBean創(chuàng)建AOP代理:


    在Spring里創(chuàng)建一個(gè)AOP代理的基本方法是使用org.springframework.aop.framework.ProxyFactoryBean。 這個(gè)類對(duì)應(yīng)用的切入點(diǎn)和通知提供了完整的控制能力(包括它們的應(yīng)用順序)轴捎。像其它的FactoryBean實(shí)現(xiàn)一樣鹤盒,ProxyFactoryBean引入了一個(gè)間接層。如果你定義一個(gè)名為foo的ProxyFactoryBean轮蜕, 引用foo的對(duì)象看到的將不是ProxyFactoryBean實(shí)例本身昨悼,而是一個(gè)ProxyFactoryBean實(shí)現(xiàn)里getObject() 方法所創(chuàng)建的對(duì)象。 這個(gè)方法將創(chuàng)建一個(gè)AOP代理跃洛,它包裝了一個(gè)目標(biāo)對(duì)象率触。


    ProxyFactoryBean類本身也是一個(gè)JavaBean,其屬性主要有如下用途:


  • 指定你希望代理的目標(biāo)對(duì)象

  • 指定是否使用CGLIB汇竭。


  • 一些主要屬性從org.springframework.aop.framework.ProxyConfig里繼承下來(這個(gè)類是Spring里所有AOP代理工廠的父類)葱蝗。這些主要屬性包括:


  • proxyTargetClass:這個(gè)屬性為true時(shí),目標(biāo)類本身被代理而不是目標(biāo)類的接口细燎。如果這個(gè)屬性值被設(shè)為true两曼,CGLIB代理將被創(chuàng)建。


  • optimize:用來控制通過CGLIB創(chuàng)建的代理是否使用激進(jìn)的優(yōu)化策略玻驻。 除非完全了解AOP代理如何處理優(yōu)化悼凑,否則不推薦用戶使用這個(gè)設(shè)置。目前這個(gè)屬性僅用于CGLIB代理璧瞬; 對(duì)于JDK動(dòng)態(tài)代理(缺省代理)無效户辫。


  • frozen:如果一個(gè)代理配置是frozen的,就不允許對(duì)該配置進(jìn)行修改嗤锉。 這在簡(jiǎn)單優(yōu)化和不希望調(diào)用者在代理創(chuàng)建后操作代理(通過Advised接口) 時(shí)很有用渔欢。缺省值為false,即可以進(jìn)行類似添加附加通知的操作瘟忱。


  • exposeProxy:決定當(dāng)前代理是否被暴露在一個(gè)ThreadLocal 中以便被目標(biāo)對(duì)象訪問奥额。如果目標(biāo)對(duì)象需要獲取代理而且exposeProxy屬性被設(shè)為 true,目標(biāo)對(duì)象可以使用AopContext.currentProxy()方法访诱。


  • aopProxyFactory:使用AopProxyFactory的實(shí)現(xiàn)垫挨。這提供了一種方法來自定義是否使用動(dòng)態(tài)代理,CGLIB或其它代理策略触菜。 缺省實(shí)現(xiàn)將根據(jù)情況選擇動(dòng)態(tài)代理或者CGLIB九榔。一般情況下應(yīng)該沒有使用這個(gè)屬性的需要;它是被設(shè)計(jì)來在Spring 1.1中添加新的代理類型的。


  • ProxyFactoryBean中需要說明的其它屬性包括:


    • proxyInterfaces:需要代理的接口名的字符串?dāng)?shù)組帚屉。 如果沒有提供,將為目標(biāo)類使用一個(gè)CGLIB代理漾峡。


    • interceptorNames:Advisor的字符串?dāng)?shù)組攻旦,可以包括攔截器或其它通知的名字。 順序是很重要的生逸,排在前面的將被優(yōu)先服務(wù)牢屋。就是說列表里的第一個(gè)攔截器將能夠第一個(gè)攔截調(diào)用。這里的名字是當(dāng)前工廠中bean的名字槽袄,包括父工廠中bean的名字烙无。這里你不能使用bean的引用因?yàn)檫@會(huì)導(dǎo)致ProxyFactoryBean忽略通知的單例設(shè)置。你可以把一個(gè)攔截器的名字加上一個(gè)星號(hào)作為后綴(*)遍尺。這將導(dǎo)致這個(gè)應(yīng)用程序里所有名字以星號(hào)之前部分開頭的通知器都被應(yīng)用截酷。


    • 單例:工廠是否應(yīng)該返回同一個(gè)對(duì)象,不論方法getObject()被調(diào)用的多頻繁乾戏。 多個(gè)FactoryBean實(shí)現(xiàn)都提供了這個(gè)方法迂苛。缺省值是true。 如果你希望使用有狀態(tài)的通知–例如鼓择,有狀態(tài)的mixin–可以把單例屬性的值設(shè)置為false來使用原型通知三幻。


    3.基于JDK和CGLIB的代理:


    如果一個(gè)需要被代理的目標(biāo)對(duì)象的類(后面將簡(jiǎn)單地稱它為目標(biāo)類)沒有實(shí)現(xiàn)任何接口,那么一個(gè)基于CGLIB的代理將被創(chuàng)建呐能。 這是最簡(jiǎn)單的場(chǎng)景念搬,因?yàn)镴DK代理是基于接口的,沒有接口意味著沒有使用JDK進(jìn)行代理的可能.


    如果ProxyFactoryBean的proxyTargetClass屬性被設(shè)為true摆出,那么一個(gè)基于CGLIB的代理將創(chuàng)建朗徊。 這樣的規(guī)定是有意義的,遵循了最小驚訝法則(保證了設(shè)定的一致性)懊蒸。甚至當(dāng)ProxyFactoryBean的proxyInterfaces屬性被設(shè)置為一個(gè)或者多個(gè)全限定接口名荣倾, 而proxyTargetClass屬性被設(shè)置為true仍然將實(shí)際使用基于CGLIB的代理。


    如果ProxyFactoryBean的proxyInterfaces屬性被設(shè)置為一個(gè)或者多個(gè)全限定接口名骑丸,一個(gè)基于JDK的代理將被創(chuàng)建舌仍。 被創(chuàng)建的代理將實(shí)現(xiàn)所有在proxyInterfaces屬性里被說明的接口; 如果目標(biāo)類實(shí)現(xiàn)了全部在proxyInterfaces屬性里說明的接口以及一些額外接口通危,返回的代理將只實(shí)現(xiàn)說明的接口而不會(huì)實(shí)現(xiàn)那些額外接口铸豁。


    如果ProxyFactoryBean的proxyInterfaces屬性沒有被設(shè)置, 但是目標(biāo)類實(shí)現(xiàn)了一個(gè)(或者更多)接口菊碟,那么ProxyFactoryBean將自動(dòng)檢測(cè)到這個(gè)目標(biāo)類已經(jīng)實(shí)現(xiàn)了至少一個(gè)接口节芥, 一個(gè)基于JDK的代理將被創(chuàng)建。被實(shí)際代理的接口將是目標(biāo)類所實(shí)現(xiàn)的全部接口; 實(shí)際上头镊,這和在proxyInterfaces屬性中列出目標(biāo)類實(shí)現(xiàn)的每個(gè)接口的情況是一樣的蚣驼。 然而,這將顯著地減少工作量以及輸入錯(cuò)誤的可能性

    最后編輯于
    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
    • 序言:七十年代末相艇,一起剝皮案震驚了整個(gè)濱河市颖杏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坛芽,老刑警劉巖留储,帶你破解...
      沈念sama閱讀 218,858評(píng)論 6 508
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異咙轩,居然都是意外死亡获讳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 93,372評(píng)論 3 395
    • 文/潘曉璐 我一進(jìn)店門活喊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丐膝,“玉大人,你說我怎么就攤上這事钾菊∮任螅” “怎么了?”我有些...
      開封第一講書人閱讀 165,282評(píng)論 0 356
    • 文/不壞的土叔 我叫張陵结缚,是天一觀的道長(zhǎng)损晤。 經(jīng)常有香客問我,道長(zhǎng)红竭,這世上最難降的妖魔是什么尤勋? 我笑而不...
      開封第一講書人閱讀 58,842評(píng)論 1 295
    • 正文 為了忘掉前任,我火速辦了婚禮茵宪,結(jié)果婚禮上最冰,老公的妹妹穿的比我還像新娘。我一直安慰自己稀火,他們只是感情好暖哨,可當(dāng)我...
      茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
    • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凰狞,像睡著了一般篇裁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赡若,一...
      開封第一講書人閱讀 51,679評(píng)論 1 305
    • 那天达布,我揣著相機(jī)與錄音,去河邊找鬼逾冬。 笑死黍聂,一個(gè)胖子當(dāng)著我的面吹牛躺苦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播产还,決...
      沈念sama閱讀 40,406評(píng)論 3 418
    • 文/蒼蘭香墨 我猛地睜開眼匹厘,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了脐区?” 一聲冷哼從身側(cè)響起集乔,我...
      開封第一講書人閱讀 39,311評(píng)論 0 276
    • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎坡椒,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尤溜,經(jīng)...
      沈念sama閱讀 45,767評(píng)論 1 315
    • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倔叼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
    • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了宫莱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丈攒。...
      茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
    • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖授霸,靈堂內(nèi)的尸體忽然破棺而出巡验,到底是詐尸還是另有隱情,我是刑警寧澤碘耳,帶...
      沈念sama閱讀 35,785評(píng)論 5 346
    • 正文 年R本政府宣布,位于F島的核電站辛辨,受9級(jí)特大地震影響指攒,放射性物質(zhì)發(fā)生泄漏允悦。R本人自食惡果不足惜隙弛,卻給世界環(huán)境...
      茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
    • 文/蒙蒙 一铣墨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧孕蝉,春花似錦降淮、人聲如沸佳鳖。這莊子的主人今日做“春日...
      開封第一講書人閱讀 31,988評(píng)論 0 22
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽科盛。三九已至贞绵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜡饵,已是汗流浹背。 一陣腳步聲響...
      開封第一講書人閱讀 33,101評(píng)論 1 271
    • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留筷登,地道東北人前方。 一個(gè)月前我還...
      沈念sama閱讀 48,298評(píng)論 3 372
    • 正文 我出身青樓苗傅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親逊桦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子强经,可洞房花燭夜當(dāng)晚...
      茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

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

    • AOP(Aspect-Oriented Programming):面向切面的編程户秤。OOP(Object-Orien...
      badcyc閱讀 299評(píng)論 0 1
    • 解釋AOP AOP(Aspect-OrientedProgramming须鼎,面向方面編程)晋控,可以說是OOP(Obje...
      jiangmo閱讀 915評(píng)論 0 2
    • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)裹唆,斷路器,智...
      卡卡羅2017閱讀 134,659評(píng)論 18 139
    • 一、簡(jiǎn)述 1蔑穴、AOP的概念 如果你用java做過后臺(tái)開發(fā),那么你一定知道AOP這個(gè)概念惧浴。如果不知道也無妨存和,套用百度...
      GitLqr閱讀 4,201評(píng)論 6 25
    • 妳手閱讀 186評(píng)論 0 2