詳解SSJ(Spring3.x mvc + Spring3.x Core + JPA2.x)輕量級集成開發—第5章 剖析Spring3.x AOP特性02

目錄

一、基於Schema風格配置AOP增強處理;

二、基於Schema風格配置全局切入點;

三、Spring AOP與AspectJ AOP的關係;

四、使用@Aspect定義切面;

五、基於Annotation風格配置AOP增強處理;

六、基於Annotation風格配置全局切入點;

 

前言

筆者在上一章節中,爲大家詳細且深入的講解了有關AOP的一些基礎知識。那麼從本章開始,咱們要開始接着學習有關Spring AOP的後續知識,這些知識包括:增強處理、切入點配置、以及如何使用基於AspectJ的方式配置Spring AOP。但是在學習這些技術之前,筆者還是要提醒各位,掌握基礎相對於進階來說是必經之路,沒有一步登天,所以耐下心學習,才能夠讓你成長的更快。

其次,有些朋友在閱讀筆者博文的時候,往往容易誤解筆者博文的標題。總是覺得筆者在講解的時候少了些許後續章節應該包含的東西,在此筆者有必要澄清一些事實。筆者打算對每一章的知識點,逐步分析逐步講解,這是需要極其漫長的過程和時間的。所以並不會在某一章節就對所有的知識點進行全方位概括,當然如果是因爲博文的標題誤導了你,筆者只能對你說聲抱歉。

最後還要提及一點的是,由於筆者會經常維護、更新早期博文的內容,所以如果大家有興趣還是可以再次進行閱讀,或許你會有意想不到的收穫。

 

一、詳解AOP之增強處理

上一章中,筆者爲大家簡單的介紹了增強處理的一些概念。還記得什麼是增強處理嗎?增強處理無非就是定義了通知的執行時機、執行順序。如果你無法理解什麼是執行時機與執行順序,那麼請你回想下咱們在上一章編寫JDK動態代理時,是否顯式的指定過代理業務的執行?其實增強處理無法就是隱式的幫你做了這些事情而已。在Spring AOP中,增強處理一共包含如下5種類型:

1、前置通知(Before advice):代理業務執行於被攔截的方法之前;

2、後置通知(After advice):代理業務執行於被攔截的方法之後;

3、環繞通知(Around advice):代理業務執行於被攔截的方法之前或之後

4、異常通知(After throwing advice):代理業務執行於被攔截的方法拋出異常後;

5、返回時通知(After returning advice):代理業務執行於被攔截的方法返回之前;

 

在基於Schema的AOP中配置中,我們可以通過使用如下標籤配置Spring AOP的增強處理:

1、<aop:before/>:用於配置前置通知(Before advice);

2、<aop:after/>:用於配置後置通知(After advice);

3、<aop:around/>:用於配置環繞通知(Around advice);

4、<aop:after-throwing/>:用於配置異常通知(After throwing advice);

5、<aop:after-returning/>:用於配置返回通知(After returning advice);

 

上述標籤我們可以將其稱之爲增強處理標籤,因爲這些標籤均帶有部分相同屬性。分別爲:method、pointcut、pointcut-ref、throwing和returning。其中屬性“method”用於指定作爲增強處理類型的切面類的指定方法。屬性“pointcut”允許定義一個表達式,該表達式的作用就是攔截指定切入點,並且該表達式支持通配符“*”和“..”。其中通配符“*”代表了任意命名模式的匹配,而“..”則代表了接受0—N個任意類型參數的方法。屬性“pointcut-ref”用於引用一個已經存在的切入點名稱,換句話來說,該屬性可以用於引用一個全局攔截切入點表達式。屬性“throwing”僅針對<aop:after-throwing/>標籤有效,該屬性用於指定一個參數,異常通知(After throwing advice)便可以通過這個參數訪問委託對象的指定方法拋出的異常。屬性“returning”同樣僅針對<aop:after-returning/>標籤有效,該屬性用於指定一個參數,返回時通知(After returning advice)便可以通過這個參數訪問委託對象的指定方法的返回值。

 

筆者打算先從前置通知(Before advice)和後置通知(After advice)開始講起,因爲這兩個通知是Spring AOP增強處理中最爲簡單,同時也是最容易理解的。前置通知(Before advice)無非就是在切入點執行之前首先執行代理業務,而後置通知(After advice)則反之。

基於Schema的風格配置Before and After增強處理:

Java代碼  收藏代碼
  1. <aop:config>  
  2.     <aop:aspect id="logAspect" ref="logBean" order="1">  
  3.         <!-- 前置通知 -->  
  4.         <aop:before method="logTest"  
  5.             pointcut="execution(* org.johngao.bean.LoginBean.*(..))" />  
  6.         <!-- 後置通知 -->  
  7.         <aop:after method="logTest"  
  8.             pointcut="execution(* org.johngao.bean.LoginBean.*(..))" />  
  9.     </aop:aspect>  
  10. </aop:config>  
  11. <bean name="logBean" class="org.johngao.bean.LogBean" />  

 

在上述配置文件中,筆者爲切入點定義了2個通知,分別爲前置通知(Before advice)和後置通知(After advice)。在切入點執行之前首先執行前置通知(Before advice),然後再執行切入點,最後執行後置通知(After advice)。其中屬性“pointcut”的值爲:"execution(* org.johngao.bean.LoginBean.*(..))" 。也就是說指定通知將攔截org.johngao.bean包下LoginBean類型的所有帶參或無參方法。當你看到這裏的時候,或許你已經明白,在一個切入點內部,允許同時定義多個通知

Before and After通知實現:

Java代碼  收藏代碼
  1. /** 
  2.  *  模擬前置通知、後置通知 
  3.  * 
  4.  *  @author JohnGao 
  5.  *  
  6.  *  @param JoinPoint: 連接點 
  7.  *  
  8.  *  @return void 
  9.  */  
  10. public void logTest(JoinPoint joinPoint)  
  11. {  
  12.     /* 獲取委託對象指定方法參數 */  
  13.     Object[] params = joinPoint.getArgs();  
  14.     for(Object param: params)  
  15.         System.out.println(param);  
  16.       
  17.     /* 獲取委託對象指定方法名稱 */  
  18.     System.out.println(joinPoint.getSignature().getName());  
  19.       
  20.     /* 獲取委託對象實例 */  
  21.     joinPoint.getTarget();  
  22.       
  23.     /* 獲取代理對象實例 */  
  24.     joinPoint.getThis();  
  25.     System.out.println("日誌記錄...");  
  26. }  

 

在上述程序示例中,筆者使用到了AspectJ提供的JoinPoint接口。開發人員使用JoinPoint接口可以很方便的訪問到委託對象的上下文信息,並且在實際開發過程中,這些上下文信息對於開發人員而言至關重要。JoinPoint接口的常用方法如下:

方法名稱 方法返回值 方法描述
getArgs() Object[] 獲取委託對象的目標方法參數列表,注意:由於返回數組所以需要拆分
getSignature() Signature 獲取委託對象的方法簽名
getTarget() Object 獲取委託對象實例
getThis() Object 獲取代理對象實例

 

當然JoinPoint接口還派生有另一個常用的擴展接口,那便是ProceedingJoinPoint接口。該接口僅限用於環繞通知(Around advice),並且相對JoinPoint接口而言,ProceedingJoinPoint接口爲開發人員提供有2個新增用於執行委託對象的方法,分別爲:

方法名稱 方法返回值 方法描述
proceed() Object 用於執行委託對象的目標方法
proceed(java.lang.Object[] args) Object 用於執行委託對象的目標方法,用新參數替換原先入參

 

至於如何使用ProceedingJoinPoint接口,大家目前不必着急,筆者在後續章節自然會進行講解。爲了更加形象的描述不同通知的執行時機與執行順序,筆者接下來會爲大家展示各種通知執行時序圖。

Before and After增強處理執行時序圖:

 

當大家理解前置通知(Before advice)和後置通知(After advice)後,筆者接下來將會爲大家講解異常通知(After throwing advice)的配置和使用。所謂異常通知(After throwing advice)無非就是在切入點拋出異常之後執行代理業務,Spring的增強處理爲開發人員提供了多種環境下執行通知的機會,在此筆者不得不佩服Rod Johnson豐富的想象力及“創造力”。

基於Schema的風格配置After throwing增強處理:

Java代碼  收藏代碼
  1. <aop:config>  
  2.     <aop:aspect id="logAspect" ref="logBean" order="1">  
  3.         <!-- 異常通知 -->  
  4.         <aop:after-throwing method="logTest"  
  5.             pointcut="execution(* org.johngao.bean.LoginBean.*(..))" />  
  6.     </aop:aspect>  
  7. </aop:config>  
  8. <bean name="logBean" class="org.johngao.bean.LogBean" />  

 

如果你定義的切入點並沒有往外拋出異常,通知是無法執行的。所以使用異常通知(After throwing advice)的時候,我們務必需要將爲切入點throws異常。

還記得筆者在上一章節提到過的throwing屬性嗎?其僅針對<aop:after-throwing/>標籤有效,該屬性用於指定一個參數,異常通知(After throwing advice)便可以通過這個參數訪問委託對象的指定方法拋出的異常。使用throwing屬性指定參數:

Java代碼  收藏代碼
  1. <aop:after-throwing method="logTest"  
  2.     pointcut="execution(* org.johngao.bean.LoginBean.*(..))"   
  3.     throwing="exception" />  

 

捕獲委託對象的指定方法拋出的異常:

Java代碼  收藏代碼
  1. /** 
  2.  *  模擬異常通知 
  3.  * 
  4.  *  @author JohnGao 
  5.  *  
  6.  *  @param JoinPoint: 連接點, Exception: 異常信息 
  7.  *  
  8.  *  @return void 
  9.  */  
  10. public void logTest(JoinPoint joinPoint, Exception exception)  
  11. {  
  12.     System.out.println(exception);  
  13. }  

 

通過上述程序示例我們可以看出,一旦委託對象的目標方法拋出異常後,我們便可以在通知中通過屬性“exception”訪問所拋出的異常信息。當然定義在通知中的方法參數,Spring的IOC容器自然會負責其初始化工作,所以你無須關心這些“瑣事”,儘可能的關注於你的業務既可。

After throwing advice增強處理執行時序圖:

 

返回時通知(After returning advice)其實也比較簡單,該通知執行於被攔截的方法返回之前。也就是說當返回時通知(After returning advice)攔截切入點後,應當首先執行切入點,最後切入點即將返回時再執行通知。

基於Schema的風格配置After returning增強處理:

Java代碼  收藏代碼
  1. <aop:config>  
  2.     <aop:aspect id="logAspect" ref="logBean" order="2">  
  3.         <!-- 返回時通知 -->  
  4.         <aop:after-returning method="logTest"  
  5.             pointcut="execution(* org.johngao.bean.LoginBean.*(..))" />  
  6.     </aop:aspect>  
  7. </aop:config>  
  8. <bean name="logBean" class="org.johngao.bean.LogBean" />  

 

還記得筆者在上一章節提到過的returning屬性嗎?其僅針對<aop:after-returning/>標籤有效,該屬性用於指定一個參數,返回時通知(After returning advice)便可以通過這個參數訪問委託對象的指定方法的返回值。使用returning屬性指定參數:

Java代碼  收藏代碼
  1. <aop:after-returning method="logTest"  
  2.     pointcut="execution(* org.johngao.bean.LoginBean.*(..))"   
  3.     returning="rvt" />  

 

獲取委託對象的目標方法返回值:

Java代碼  收藏代碼
  1. /** 
  2.  *  模擬返回時通知 
  3.  * 
  4.  *  @author JohnGao 
  5.  *  
  6.  *  @param JoinPoint: 連接點, Object: 返回值信息 
  7.  *  
  8.  *  @return void 
  9.  */  
  10. public void logTest(JoinPoint joinPoint, Object rvt)  
  11. {  
  12.     System.out.println(rvt);  
  13. }  

 

通過上述程序示例我們可以看出,如果需要獲取委託對象的目標方法的返回值時,我們可以通過定義<aop:after-returning/>標籤中的“returning”屬性即可。但這裏需要注意的是,returning屬性的屬性名稱務必和通知方法中的屬性名稱保持一致

 

After returning advice增強處理執行時序圖:

 

 

筆者至此已經爲大家講解了前置(Before advice)、後置(After advice)、異常(After throwing advice)、返回時(After returning advice)等4種通知的配置和使用,那麼接下來筆者就開始講解環繞通知(Around advice)。至於爲什麼需要將環繞通知(Around advice)放在最後一個講解?並不是因爲它相對其他幾個通知更復雜,而是因爲這個通知更特殊

但從字面上的理解,很多開發人員會錯誤的將環繞通知(Around advice)理解爲是前置通知(Before advice)和後置通知(After advice)的結合體。以爲該通知無非就是在切入點的執行前後各執行一次,其實這是錯誤的,筆者希望大家不要因爲字面的顯淺理解就妄下定論,免得貽笑大方。

環繞通知(Around advice)適用的場景更多的基於併發環境,並且該通知可以滿足於切入點之前或者之後執行,甚至可以根據實際業務來判斷是否執行。這纔是使用環繞通知(Around advice)真正的目的。

基於Schema的風格配置Around增強處理:

Java代碼  收藏代碼
  1. <aop:config>  
  2.     <aop:aspect id="logAspect" ref="logBean" order="1">  
  3.         <!-- 環繞通知 -->  
  4.         <aop:around method="logTest"  
  5.             pointcut="execution(* org.johngao.bean.LoginBean.*(..))" />  
  6.     </aop:aspect>  
  7. </aop:config>  
  8. <bean name="logBean" class="org.johngao.bean.LogBean" />  

 

ProceedingJoinPoint接口派生於JoinPoint接口,該接口僅限於環繞通知(Around advice)獲取委託對象的上下文信息使用。筆者剛纔也提到過,在實際開發過程中,我們可以使用環繞通知(Around advice)根據實際業務,決定通知是否執行,以及何時執行。

Around通知實現

Java代碼  收藏代碼
  1. /** 
  2.  *  模擬環繞通知 
  3.  * 
  4.  *  @author JohnGao 
  5.  *  
  6.  *  @param ProceedingJoinPoint: 連接點 
  7.  *  
  8.  *  @return void 
  9.  */  
  10. public void logTest(ProceedingJoinPoint proceedingJoinPoint)   
  11.         throws Throwable  
  12. {  
  13.     System.out.println("日誌記錄...");  
  14.       
  15.     /* 執行委託對象的目標方法 */  
  16.     proceedingJoinPoint.proceed();  
  17.     System.out.println("日誌記錄...");  
  18. }  

 

ProceedingJoinPoint接口的proceed()方法用於執行委託對象的目標方法。然而ProceedingJoinPoint接口還提供有另外一個帶參的proceed(java.lang.Object[] args)方法,該方法除了可以用於執行委託對象的目標方法外,還支持使用新參數替換原先入參。

使用proceed(java.lang.Object[] args)方法替換原先入參:

Java代碼  收藏代碼
  1. /* 執行委託對象的目標方法 */  
  2. proceedingJoinPoint.proceed(new Object[]{"新入參,替換原先入參"});  

 

一旦使用proceed(java.lang.Object[] args)方法替換原先入參後,新參數將會覆蓋之前傳遞給委託對象的目標方法參數。當然如果你不希望替換原先入參,筆者建議你還是使用proceed()方法即可。

二、基於Schema風格配置全局切入點

在5種通知標籤中,我們可以通過使用pointcut屬性定義一個表達式,該表達式的作用就是攔截指定切入點。只不過所配置的切入點的作用域僅針對對應的切面有效,換句話來說使用pointcut屬性定義的攔截切入點表達式作用域是局部的。但是在實際開發過程中,我們往往需要定義一些通用的全局攔截切入點表達式,該如何實現呢?值得慶幸的是Spring爲咱們提供有<aop:pointcut/>標籤以滿足開發人員的需求。

使用<aop:pointcut/>標籤定義全局攔截切入點表達式相當簡單,你僅僅只需要聲明,然後在通知標籤中使用屬性“pointcut-ref”引用即可。這樣一來,我們就可以定義一些通用的攔截切入點表達式,而不必每次都在通知標籤中重複定義

使用<aop:pointcut/>標籤定義全局攔截切入點表達式:

Java代碼  收藏代碼
  1. <aop:config>  
  2.     <aop:pointcut expression="execution(* org.johngao.bean.LoginBean.*(..))"  
  3.         id="pointcutTest" />  
  4.     <aop:aspect id="logAspect" ref="logBean" order="1">  
  5.         <!-- 環繞通知 -->  
  6.         <aop:around method="logTest" pointcut-ref="pointcutTest" />  
  7.     </aop:aspect>  
  8. </aop:config>  
  9. <bean name="logBean" class="org.johngao.bean.LogBean" />  

 

三、Spring AOP與AspectJ AOP的關係

AspectJ是Java平臺誕生的第一個AOP Framework,可以毫不客氣的說AspectJ已經成爲AOP領域的規範制定者。遵循AspectJ規範,也就是在遵循AOP的標準。目前市面上諸多AOP Framework都在借鑑AspectJ的一些思想,其中就包括Spring。值得慶幸的是AspectJ完全是開源的,並且完全採用Java語言編寫的,開發人員可以自由下載AspectJ的源碼進行研究和學習。

Spring針對AspectJ進行了很好的集成支持,並且Spring允許開發人員直接在Spring中使用AspectJ進行AOP編程。當然筆者並不打算對AspectJ進行深入講解,感興趣的朋友可以自行下載AspectJ的依賴構件及API。

或許談到現在,有很多朋友還是不明白Spring AOP與AspectJ到底存在什麼關係,難道僅僅只是遵循了AspectJ的規範進行自定義編制嗎?其實不是的,Spring AOP與AspectJ從嚴格意義上來說完全是兩碼事,Spring AOP更像是一個粘合劑。除了允許你使用Spring的原生AOP實現,同時還支持你使用AspectJ作爲Spring的AOP實現。早在Spring1.x的時代,由於那時候Spring還並未集成AspectJ,所以那時候的開發人員都只能使用Spring的原生AOP。但現在不同了,你完全可以使用AspectJ作爲你的AOP實現,並且脫離Spring,AspectJ同樣也能夠單獨使用。對於目前的開發團隊而言,已經很少有人繼續使用Spring的原生AOP來滿足項目需要,更多的均是採用集成AspectJ的方式。因爲這不僅僅是遵循一種規範,更重要的是使用AspectJ可以簡化編碼量。所謂開發實惠,就是這個道理,選擇解耦的同時,注重開發效率也是一個優秀團隊應該考慮的首要問題。

在上一章中,筆者跟大家提及過JDK動態代理和cglib動態代理。至於爲什麼要學習這2種代理,那是因爲幾乎所有的AOP Framework的底層實現均是使用這2種代理方式。JDK動態代理相對於cglib是有侷限性的,因爲JDK自身只支持基於接口的代理,而不支持類型的代理。當遇到代理類型是類類型的時候,我們或許可以考慮使用cglib。Spring AOP同樣也是這麼做的,Spring缺省使用JDK動態代理來作爲AOP底層實現,那是爲了實現高內聚、低耦合,Spring遵循了面向接口編程而已。只有當需要代理的爲非接口類型時,Spring纔會自動切換cglib作爲AOP的底層實現。

最後你只需要明白一旦在Spring中使用AspectJ進行AOP編程,Spring AOP則依賴於AspectJ,而AspectJ的底層實現仍然是採用JDK動態代理和cglib動態代理。

Spring AOP與AspectJ AOP的依賴關係圖:

 

提示:

筆者在此還要補充一點的是,AspectJ採用的是編譯時增強的解決方案。這與Spring原生的AOP實現是不同的,Spring的原生AOP實現採用的是代理實現方式,這2種底層實現方式的不同,並不代表着性能差距會很大,你只需關注你的業務即可。

 

四、使用@Aspect定義切面

AspectJ允許使用Annotation的方式來定義切面、增強類型以及切入點。當然你不用去關注Spring與AspectJ底層依賴的一些“瑣事”,因爲你根本沒有必要理解這些東西,你只需要明白接下來咱們要做的事情就是在Spring中使用AspectJ提供的Annotation進行AOP編程即可。

我們可以使用AspectJ提供的@Aspect來定義一個切面類,但是在正式使用之前,我們必須要在IOC配置文件中添加AspectJ的支持,因爲只有這樣才能正常使用AspectJ AOP。

啓動AspectJ AOP支持:

Java代碼  收藏代碼
  1. <!-- 啓動AspectJ支持 -->  
  2. <aop:aspectj-autoproxy />  

 

在第四章的時候,筆者爲大家講解了<context:component-scan/>標籤的使用。既然我們使用的是AspectJ定義切面,那麼必然我們還需要在自動掃包的時候,能夠自動掃描定義的所有切面組件。<context:component-scan/>標籤中包含了一個<context:include-filter/>子標籤,該標籤的作用就是IOC容器啓動時,除了會自動掃描項目中所有的Bean組件外,還會掃描定義好的所有切面組件。

使用<context:include-filter/>標籤自動掃描切面組件:

Java代碼  收藏代碼
  1. <context:component-scan base-package="*">  
  2.     <context:include-filter type="annotation"  
  3.         expression="org.aspectj.lang.annotation.Aspect" />  
  4. </context:component-scan>  

 

如果使用Annotation的方式定義切面,咱們就可以將以前以Schema風格定義在配置文件中的切面信息完全移除。開發人員只需在切面類上方加上@Aspect標註即可。

使用@Aspect定義切面類:

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     //...  
  5. }  

 

通過上述程序示例我們可以看出,使用@Aspect可成功定義一個切面類。相對於以Schema風格定義切面類來說確實方便了不少,同時也爲IOC配置文件進行了極大的瘦身

 

五、基於Annotation風格配置AOP增強處理

使用Annotation的方式配置AOP增強處理,主要使用到的Annotation爲如下5種:
1、@Before:用於配置前置通知(Before advice);

2、@After:用於配置後置通知(After advice);

3、@Around:用於配置環繞通知(Around advice);

4、@AfterThrowing:用於配置異常通知(After throwing advice);

5、@afterReturning:用於配置返回通知(After returning advice);

 

使用@Before配置前置通知(Before advice):

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     @Before("execution(* org.johngao.bean.*.*(..))")  
  5.     public void logTest(JoinPoint joinPoint)   
  6.     {  
  7.         System.out.println("日誌記錄...");  
  8.     }  
  9. }  

 

使用@After用於配置後置通知(After advice):

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     @After("execution(* org.johngao.bean.*.*(..))")  
  5.     public void logTest(JoinPoint joinPoint)   
  6.     {  
  7.         System.out.println("日誌記錄...");  
  8.     }  
  9. }  

 

使用@Around配置環繞通知(Around advice):

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     @Around("execution(* org.johngao.bean.*.*(..))")  
  5.     public void logTest(ProceedingJoinPoint proceedingJoinPoint)   
  6.             throws Throwable  
  7.     {  
  8.         System.out.println("日誌記錄...");  
  9.           
  10.         /* 執行委託對象的目標方法 */  
  11.         proceedingJoinPoint.proceed();  
  12.         System.out.println("日誌記錄...");  
  13.     }  
  14. }  

 

使用@AfterThrowing配置異常通知(After throwing advice):

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     @AfterThrowing(pointcut = "execution(* org.johngao.bean.*.*(..))",   
  5.             throwing="exception")  
  6.     public void logTest(JoinPoint joinPoint, Exception exception)   
  7.     {  
  8.         System.out.println("異常: " + exception);  
  9.         System.out.println("日誌記錄...");  
  10.     }  
  11. }  

 

使用@AfterReturning:用於配置返回通知(After returning advice):

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean   
  3. {  
  4.     @AfterReturning(pointcut = "execution(* org.johngao.bean.*.*(..))",   
  5.             returning ="rvt")  
  6.     public void logTest(JoinPoint joinPoint, Object rvt)   
  7.     {  
  8.         System.out.println("返回值: " + rvt);  
  9.         System.out.println("日誌記錄...");  
  10.     }  
  11. }  

 

在@AfterThrowing和@AfterReturning的內部,都包含一個叫做pointcut的屬性。在基於Schema風格的配置中,我們都是使用這個屬性來定義攔截切入點表達式。但是其內部缺省的value屬性也可以用於定義攔截切入點表達式,那麼我們應該如何選擇呢?來看看Spring的官方解釋

 

通過Spring的官方解釋我們可以看出,缺省情況下以value屬性定義攔截切入點表達式,如果顯示指定pointcut作爲攔截切入點表達式後,pointcut將重寫value屬性的定義。

 

六、基於Annotation風格配置全局切入點

在基於Schema的配置風格中,我們可以使用<aop:pointcut/>標籤來配置全局攔截點表達式。而一旦我們使用基於Annotation的方式後,則可以使用@Pointcut的方式配置全局攔截點表達式。@Pointcut可以適用於委託對象的目標方法之上,同樣也可以適用於通知上。當然具體怎麼使用就根據項目需要或者你的個人喜好而定。

使用@Pointcut配置全局切入點:

Java代碼  收藏代碼
  1. @Aspect  
  2. public class LogBean {  
  3.     @Before(value ="testPointcut()")  
  4.     public void logTest() {  
  5.         System.out.println("日誌記錄...");  
  6.     }  
  7.       
  8.     @Pointcut("execution(* org.johngao.bean.*.*(..))")  
  9.     public void testPointcut() {  
  10.         //...  
  11.     }  
  12. }  

 

如果其他切面類也需要使用這個全局的攔截點表達式,則可以使用類名.方法名的方式進行引用

Java代碼  收藏代碼
  1. @Before(value ="LogBean.testPointcut()")  

 

本章內容到此結束,由於時間倉庫,本文或許有很多不盡人意的地方,希望各位能夠理解和體諒。關於下一章的內容,筆者打算講解Spring3.x MVC相關的內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章