Spring AOP筆記

筆記

學習資料來自Spring Tutorial 24 - Introduction to AOP

Video 1

Functional Programming.

Difference between FP and Object Oriented Programming.

問題
但是這里有個問題总寒,并不是所有的處理都可以規(guī)約到某個class里的。

比如每個class都會用到的方法刁赖,例如Logger贬蛙。

一個比較naive的想法是我們可以將這些方法抽象成一個新的class,
然后其他的class引用這個抽象出來的公共class锰提。

抽象成一個Logger類也存在一些問題曙痘。

  • 和業(yè)務(wù)類關(guān)聯(lián)過多
  • 業(yè)務(wù)類仍然需要調(diào)用Logger類的方法
  • 無法一次性修改所有的方法

AOP解決了這個問題。

通過創(chuàng)建一些Aspect立肘,例如LoggingAspect边坤,
來解決這個問題。
這樣我們就不用修改我們的業(yè)務(wù)代碼谅年,業(yè)務(wù)代碼是非常干凈的茧痒。

然后我們通過Aspect Configuration來讓Aspect和業(yè)務(wù)代碼交互工作。

Aspect允許我們在目標方法的前后wrapping一些特定的代碼融蹂。

實現(xiàn)步驟:

  • 編寫Aspect
  • 配置Aspect

Video 4

如何實現(xiàn)一個最簡單的AOP配置旺订。
由于這個視頻比較老弄企,2011年的視頻,所以基本上是基于xml進行的配置耸峭。
我查閱了相關(guān)的資料桩蓉,用annotation配置了一遍,
所以這個project是沒有用到任何xml的劳闹。

4.1 創(chuàng)建一個class LoggingAspect

用@Aspect 和 @Component標記這個class院究,
前者聲明這個class是一個aspect類,后者聲明這個class為Spring中的一個bean本涕。

4.2 在LoggingAspect中創(chuàng)建一個method

用@Before標記這個method业汰,
表示這個方法將在某個特定的條件下被執(zhí)行。

這里視頻中使用@Before("execution(public String getName())")菩颖,
表示在遇到滿足getNawme條件的方法被執(zhí)行時样漆,這個被標記的方法會在這之前被執(zhí)行。

4.3 創(chuàng)建class AppConfig

并標記為@Configuration和@EnableAspectJAutoProxy晦闰。
讓Aspect的配置有效化放祟。

That's it!

這樣我們就實現(xiàn)了一個最基本的AOP。

啟動應(yīng)用呻右,然后在網(wǎng)址中輸入localhost:8080/circle/xxx跪妥。
如果可以看到console口輸出了Aspect中的內(nèi)容(Advice run. Get Method called),那么你就成功了声滥。

Video 5

5.1 WildCard.

execution(* get*())好像在我的這個版本的Spring中不管用眉撵,一直報錯。

找到了原因是因為這里的get設(shè)置太廣泛落塑,導(dǎo)致一些內(nèi)置的tomcat的一些類也被aop了纽疟,
由于一些方法無法訪問到所以一直報錯無法啟動

execution(* com.zyd.model.*.get*())

一些通配符的使用方法,

  • 返回類型
  • 限制package
  • 方法名的通配符
  • 方法參數(shù)的通配符

使用通配符的目的是讓我們可以一次性匹配多個方法憾赁,因為通常我們希望切入的方法不止一個污朽。

5.2 Pointcut.

通過創(chuàng)建Pointcut我們可以抽象出一些切入點,并且其他需要做AOP的方法就不需要自己定義何時執(zhí)行龙考,
而是直接調(diào)用引用定義好的Pointcut就行膘壶。

很明顯,如果我們給每個Aspect方法都創(chuàng)建一個單獨的匹配(execution之類的)洲愤,
那么一旦我們修改了業(yè)務(wù)邏輯中的類或者方法名,
我們想要再修改Aspect中的配置的話會非常的繁瑣顷锰,
如果我們把這些匹配都抽象成Pointcut的話管理起來會非常的方便柬赐。

Video 6

一些關(guān)于Pointcut的配置。

  • execution:作用于方法
  • within:作用于類

Pointcut的組合官紫。

allGetters() && allCircleMethods()  

通過組合用更少的Pointcut設(shè)計出更多的pattern肛宋。

隨著我們的業(yè)務(wù)邏輯越來越復(fù)雜州藕,我們可能會創(chuàng)建出非常復(fù)雜的Pointcut,
對于閱讀代碼的人來說很不友好酝陈,對于維護者來說也很難下手床玻。
如果我們可以將復(fù)雜的Pointcut拆分成多個簡單的Pointcut,并且通過排列組合來復(fù)用這些邏輯沉帮,
很顯然是一個非常好的選擇锈死。

Video 7

JoinPoints。
一般用在方法上穆壕〈#可以獲取到執(zhí)行方法的一些信息。

  • toString:執(zhí)行了什么方法
  • so on

@Before("args(some-args)")
我們也可以在設(shè)置Pointcut的時候指定目標函數(shù)的執(zhí)行參數(shù)喇勋,
這樣我們可以在Aspect里面獲取到函數(shù)執(zhí)行的參數(shù)值進行一些處理缨该。

有時候我們不光是希望切入到某個方法中,在他的之前或者之后做一些事情川背,
我們同時也希望獲取到目標方法的一些信息贰拿,這樣能更靈活的執(zhí)行我們的Aspect邏輯。
比如日志記錄切入方法的執(zhí)行參數(shù)值熄云,返回類型等等膨更。
那么JoinPoints就給我們提供了這樣一個接口來實現(xiàn)這些功能。

Video 8

  • @After
  • @AfterReturning
  • @AfterThrowing

After稍微特殊一點皱碘,因為函數(shù)執(zhí)行可能會拋出異常询一,
所以我們可以設(shè)置一些pointcut,他們的執(zhí)行條件為要么函數(shù)正常返回癌椿,要么拋出異常健蕊。

@AfterReturning(pointcut='point-cut', returning='returnVal')
通過這樣的方式我們可以獲取到切入方法的返回值來進行處理。
比如在某些場景中踢俄,我們希望日志記錄某些特定方法的返回值缩功,來進行異常排查等等。

同理都办,
@AfterThrowing(pointcut='point-cut', throwing='ex')
我們也可以在Aspect中獲取到目標函數(shù)拋出的異常嫡锌。

Video 9

Around.

可以包裹目標函數(shù),甚至決定是否執(zhí)行目標函數(shù)琳钉。
一般可以用來做filter势木。

但是通常來說,我們要盡可能遵循最小原則歌懒,
如果你知道你的Aspect只需要在目標函數(shù)之后執(zhí)行啦桌,那么用@Before就足夠了。

Video 10

Naming Conversion非常的重要。
因為我們在描述匹配的時候我們是用的字符串匹配甫男,
所以如果一個項目的組員不遵守一定的命名規(guī)則的話且改,
那么很容易會匹配不上某些類或者匹配到一些不想匹配的類。

使用Annotation來反向配置Aspect板驳。

  • 編寫Aspect方法
  • 編寫自定義的annotation
  • 配置Aspect方法又跛,綁定方法到某個annotation上
  • 在我們想要應(yīng)用此Aspect方法的業(yè)務(wù)類方法上使用這個annotation

這樣,業(yè)務(wù)類中的方法就和特定的Aspect方法綁定上了若治。(通過annotation)

為什么要這么做慨蓝?
因為有時候我們想要給某些特定的方法綁定Aspect,
但是這些特定的方法很難找到規(guī)律直砂,(意味著我們很難寫出通用的Pointcut)菌仁,
這時候通過annotation來綁定會顯得更加靈活。
但同時也增加了業(yè)務(wù)類的負擔静暂,因為他們要維護Aspect的配置济丘。

Video 11

使用xml進行AOP的配置。
但是作者也強調(diào)說個人更喜歡annotation方式的配置洽蛀,
但是畢竟有一些老項目可能還在使用xml的配置方式摹迷,
所以學習xml配置并無壞處。

Video 12

AOP的底層原理用到了代理模式郊供。
簡單的來說目標類被代理類繼承峡碉,
代理類重寫了目標方法,并且在原始的方法的before和after的部分加入Aspect的邏輯驮审。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲫寄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疯淫,更是在濱河造成了極大的恐慌地来,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熙掺,死亡現(xiàn)場離奇詭異未斑,居然都是意外死亡,警方通過查閱死者的電腦和手機币绩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門蜡秽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人缆镣,你說我怎么就攤上這事芽突。” “怎么了董瞻?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵诉瓦,是天一觀的道長。 經(jīng)常有香客問我,道長睬澡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任眠蚂,我火速辦了婚禮煞聪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逝慧。我一直安慰自己昔脯,他們只是感情好,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布笛臣。 她就那樣靜靜地躺著云稚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沈堡。 梳的紋絲不亂的頭發(fā)上静陈,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天,我揣著相機與錄音诞丽,去河邊找鬼鲸拥。 笑死,一個胖子當著我的面吹牛僧免,可吹牛的內(nèi)容都是我干的刑赶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼懂衩,長吁一口氣:“原來是場噩夢啊……” “哼撞叨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起浊洞,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤牵敷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后沛申,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體劣领,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年铁材,在試婚紗的時候發(fā)現(xiàn)自己被綠了尖淘。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡著觉,死狀恐怖村生,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饼丘,我是刑警寧澤趁桃,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響卫病,放射性物質(zhì)發(fā)生泄漏油啤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一蟀苛、第九天 我趴在偏房一處隱蔽的房頂上張望益咬。 院中可真熱鬧,春花似錦帜平、人聲如沸幽告。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽冗锁。三九已至,卻和暖如春嗤栓,著一層夾襖步出監(jiān)牢的瞬間冻河,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工抛腕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留芋绸,地道東北人。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓担敌,卻偏偏與公主長得像摔敛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子全封,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344