javascript
Spring in Action 4 读书笔记之使用标签创建 AOP
目錄
在之前的讀書筆記?Spring in Acton 4 讀書筆記之 AOP 原理及 Spring 對 AOP 的支持?中,講到 Spring 對 AOP 的支持包含四方面:
Spring in Action(Spring 實戰(zhàn))的第四章第三節(jié)(4.3 Creating annotated aspects)講述了其中第三種,即如何使用標簽創(chuàng)建 aspect。本文講解其中的前面兩小節(jié):定義 aspect 以及創(chuàng)建 around advice。
AspectJ 5 引進的主要特性是使用標簽創(chuàng)建 aspect。AspectJ 5 的缺點是需要學(xué)習(xí)擴展的 java 語言。但是 AspectJ 面向標簽的編程模式使得將一個類轉(zhuǎn)換成 aspect 變得很容易,只需要在類中加一些標簽。
定義一個 aspect
以下是使用標簽創(chuàng)建 AOP 的例子,這個例子在之前的文章中有提到過,觀眾在演出開始前后,以及出問題時,會自動做出一些反應(yīng):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | package concert; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; @Aspect public class Audience { @Before("execution(** concert.Performance.perform(..))") public void silenceCellPhones() { System.out.println("Silencing cell phones"); } @Before("execution(** concert.Performance.perform(..))") public void takeSeats() { System.out.println("Taking seats"); } @AfterReturning("execution(** concert.Performance.perform(..))") public void applause() {  System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("execution(** concert.Performance.perform(..))") public void demandRefund() { System.out.println("Demanding a refund"); } } |
Audience 類上加上 @Aspect,用來表示 Audience 是一個 aspect,而 Audience 被標注的方法定義了具體的行為。在表演開始前,觀眾需要就座(takeSeats()),將手機靜音(silenceCellPhones())。
表演結(jié)束后,觀眾需要鼓掌(applause()),如果表演過程中出現(xiàn)了異常,觀眾會要求退票(demandRefund())。AspectJ 提供了五個標簽來定義 advice:
- @After,在方法正常執(zhí)行結(jié)束,或者出現(xiàn)異常的時候,執(zhí)行 aspect。
- @AfterReturning,在方法正常執(zhí)行結(jié)束后,執(zhí)行 aspect。
- @AfterThrowing,在方法拋出異常的時候,執(zhí)行 aspect。
- @Around,在方法執(zhí)行過程中,執(zhí)行 aspect。
- @Before, 在方法執(zhí)行之前,執(zhí)行 aspect。
上面的例子中,所有標簽的值都是一個 pointcut 表達式,而且在這個例子里,正好是一樣的(因為是作用在同一個方法上)。實際上,可以將這個 pointcut 定義好,然后進行引用,這樣可以避免重復(fù)編寫 pointcut。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @Aspect public class Audience { @Pointcut("execution(** concert.Performance.perform(..))") public void performance() {}  @Before("performance()") public void silenceCellPhones() { System.out.println("Silencing cell phones"); } @Before("performance()") public void takeSeats() { System.out.println("Taking seats"); } @AfterReturning("performance()") public void applause() { System.out.println("CLAP CLAP CLAP!!!"); } @AfterThrowing("performance()") public void demandRefund() { System.out.println("Demanding a refund"); } } |
上面的代碼,使用 @Pointcut 標簽對 performance()方法進行標注,這樣,就可以直接使用 performance()來代替 pointcut 表達式了。performance()只是一個標記,所以方法體可以也必須是空的。
如果只是定義了上面 Audience 這個 aspect, 那么其實什么也做不了。必須有一個配置文件,指出它是一個 aspect,并且解析這些標簽,然后創(chuàng)建代理,最終將 Audience 轉(zhuǎn)化為一個 aspect。
如果是使用 JavaConfig, 可以在配置文件類加上 @EnableAspectJAutoProxy 標簽,以實現(xiàn)自動代理。以下是示例:
| 1 2 3 4 5 6 7 8 9 | @Configuration @EnableAspectJAutoProxy @ComponentScan public class ConcertConfig { @Bean public Audience audience() { return new Audience(); } } |
Spring 使用 AspectJ 進行自動代理,僅僅是使用 @AspectJ 的標簽作為指引,而底層仍然是 Spring 自己的基于代理的 aspect。所以,盡管使用了 @AspectJ 標簽,Spring 的 AOP 仍然只能作用在方法級別。如果要使用 AspectJ 的全部功能,就必須在運行時注入 AspectJ,而不使用 Spring 來創(chuàng)建基于代理的 aspect。
創(chuàng)建一個 around advice
前面講解了 before 和 after 的用法,由于 around 的用法有些不同,也更有用,所以這里單講。先看看下面的例子:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Aspect public class Audience { @Pointcut("execution(** concert.Performance.perform(..))") public void performance() {} @Around("performance()") public void watchPerformance(ProceedingJoinPoint jp) { try { System.out.println("Silencing cell phones"); System.out.println("Taking seats"); jp.proceed(); System.out.println("CLAP CLAP CLAP!!!"); } catch (Throwable e) { System.out.println("Demanding a refund"); } } } |
使用 @Around 標簽標注了 watchPerformance 方法,監(jiān)聽 performance()代表的 joinpoint。此時,watchPerformance 的參數(shù) ProceedingJoinPoint 就是指這個 joinpoint。可以看到,在 jp.proceed()的前后各有一些操作,甚至在拋出異常時,也有一些處理。所以,這個方法同時實現(xiàn) @Before、@AfterReturning 和 @AfterThrowing 等標簽的功能,更加靈活。
需要注意的是,必須執(zhí)行 joinpoint 的 proceed()方法,否則,會導(dǎo)致被監(jiān)聽的方法沒有執(zhí)行。
我計劃完成 50 到 100 篇關(guān)于 Spring 的文章,這是第十一篇,歡迎訂閱 tantanit.com,第一時間獲取文章更新,本文鏈接地址:http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/
談?wù)?IT的文章均為原創(chuàng)或翻譯(翻譯會注明外文來源),轉(zhuǎn)載請以鏈接形式標明本文地址:?http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/
from:?http://tantanit.com/springinaction4-du-shu-bi-ji-zhi-shi-yong-biao-qian-chuang-jian-aop/
總結(jié)
以上是生活随笔為你收集整理的Spring in Action 4 读书笔记之使用标签创建 AOP的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《spring实战第四版》的读书笔记
- 下一篇: JavaScript的5种调用函数的方法