1. 程式人生 > >Spring4之AOP註解配置詳解

Spring4之AOP註解配置詳解

啟動AOP配置

要在 Spring 應用中使用 AspectJ 註解,需要如下支援:

1. 在 classpath 下包含 AspectJ 類庫:aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar

2. 將 aop Schema 新增到 Bean 配置檔案 <beans> 根元素中。

3. 在 Bean 配置檔案中定義一個空的 XML 元素 <aop:aspectj-autoproxy><aop:aspectj-autoproxy/>

注:當 Spring IOC 容器偵測到 Bean 配置檔案中的<aop:aspectj-autoproxy><aop:aspectj-autoproxy/> 元素時,會自動為與 AspectJ 切面匹配的 Bean 建立代理。

用 AspectJ 註解宣告切面

要在 Spring 中宣告 AspectJ 切面,只需要在 IOC 容器中將切面宣告為 Bean 例項。當在 Spring IOC 容器中初始化 AspectJ 切面之後,Spring IOC 容器就會為那些與 AspectJ 切面相匹配的 Bean 建立代理。在 AspectJ 註解中,切面只是一個帶有 @Aspect 註解的 Java 類。通知是標註有某種註解的簡單的 Java 方法。

AspectJ 支援 5 種類型的通知註解:

@Before:前置通知,在方法執行之前執行

@After:後置通知,在方法執行之後執行 

@AfterRunning:返回通知,在方法返回結果之後執行

@AfterThrowing:異常通知,在方法丟擲異常之後

@Around:環繞通知,圍繞著方法執行

前置通知

前置通知:在方法執行之前執行的通知。

前置通知使用 @Before 註解,並將切入點表示式的值作為註解值。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 把這個類宣告為一個切面: 
  3.  * 1. 使用註解“@Repository”把該類放入到IOC容器中 
  4.  * 2. 使用註解“@Aspect”把該類宣告為一個切面 
  5.  *  
  6.  * 設定切面的優先順序: 
  7.  * 3. 使用註解“@Order(number)”指定前面的優先順序,值越小,優先順序越高 
  8.  */  
  9. @Order
    (1)  
  10. @Aspect  
  11. @Repository  
  12. public class DaoLogAspect {  
  13.     /** 
  14.      * 宣告該方法是一個前置通知:在目標方法開始之前執行 
  15.      * '@Before'標識這個方法是個前置通知,切點表示式表示執行 UserDao類的 insert(User user) 方法. 
  16.      */  
  17.     @Before("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")  
  18.     public void beforeInsert()  
  19.     {  
  20.         System.out.println("--beforeInsert------------");  
  21.     }  
  22. }  

利用方法簽名編寫 AspectJ 切入點表示式

最典型的切入點表示式是根據方法的簽名來匹配各種方法:

execution * xyz.huning.spring4.aop.dao.impl.UserDao.*(..):匹配UserDao中宣告的所有方法,第一個 * 代表任意修飾符及任意返回值。第二個 * 代表任意方法。 .. 匹配任意數量的引數。若目標類與介面與該切面在同一個包中,可以省略包名。

execution public * UserDao.*(..):匹配 UserDao類的所有公有方法。

execution public double UserDao.*(..):匹配 UserDao中返回 double 型別數值的方法。

execution public double UserDao.*(double, ..):匹配第一個引數為 double 型別的方法, .. 匹配任意數量任意型別的引數。

execution public double UserDao.*(double,double):匹配引數型別為 double,double 型別的方法。

合併切入點表示式

在 AspectJ 中,切入點表示式可以通過操作符 &&,||,! 結合起來。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 合併切入點表示式 
  3.  * 在 AspectJ 中,切入點表示式可以通過操作符 &&,||,! 結合起來。 
  4.  */  
  5. @Pointcut("execution(* *.insert(..)) || execution(* *.delete(..))")  
  6. public void insertDeleteJoinPoint(){}  

讓通知訪問當前連線點的細節

可以在通知方法中宣告一個型別為 JoinPoint 的引數。然後就能訪問連結細節。如方法名稱和引數值。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 宣告該方法是一個前置通知:在目標方法開始之前執行 
  3.  */  
  4. @Before("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")  
  5. public void beforeInsert(JoinPoint joinPoint)  
  6. {  
  7.     System.out.println("--beforeInsert with joinPoint------------");  
  8.     //獲取方法名稱  
  9.     String methodName = joinPoint.getSignature().getName();  
  10.     //獲取引數值  
  11.     String args = Arrays.toString(joinPoint.getArgs());  
  12.     System.out.println("Taget method: " + methodName);  
  13.     System.out.println("Taget method args: " + args);  
  14. }  

後置通知

後置通知是在連線點完成之後執行的, 即連線點返回結果或者丟擲異常的時候,下面的後置通知記錄了方法的終止。

一個切面可以包括一個或者多個通知。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 宣告該方法是一個後置通知:在目標方法開始之後執行(即使目標方法執行出現異常也會執行) 
  3.  * 後置通知中不能訪問目標方法的執行結果 
  4.  */  
  5. @After("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")  
  6. public void afterInsert()  
  7. {  
  8.     System.out.println("--afterInsert------------");  
  9. }  

返回通知

無論連線點是正常返回還是丟擲異常,後置通知都會執行。如果只想在連線點返回的時候記錄日誌,應使用返回通知代替後置通知。在返回通知中,只要將 returning 屬性新增到 @AfterReturning 註解中,就可以訪問連線點的返回值。該屬性的值即為用來傳入返回值的引數名稱。必須在通知方法的簽名中新增一個同名引數。在執行時,Spring AOP 會通過這個引數傳遞返回值。原始的切點表示式需要出現在 pointcut 屬性中。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 宣告該方法是一個返回通知:在目標方法正常結束之後返回(目標方法執行出現異常時不再執行) 
  3.  * 返回通知可以訪問目標方法的執行結果 
  4.  */  
  5. @AfterReturning(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.query(..))",returning="result")  
  6. public void afterQueryReturning(JoinPoint joinPoint,Object result)  
  7. {  
  8.     System.out.println("--afterQueryReturning with joinPoint and result------------");  
  9.     String methodName = joinPoint.getSignature().getName();  
  10.     String args = Arrays.toString(joinPoint.getArgs());  
  11.     System.out.println("Taget method: " + methodName);  
  12.     System.out.println("Taget method args: " + args);  
  13.     System.out.println("Taget method execute result: " + result);  
  14. }  

異常通知

只在連線點丟擲異常時才執行異常通知,將 throwing 屬性新增到 @AfterThrowing 註解中,也可以訪問連線點丟擲的異常。Throwable 是所有錯誤和異常類的超類。所以在異常通知方法可以捕獲到任何錯誤和異常。如果只對某種特殊的異常型別感興趣,可以將引數宣告為其他異常的引數型別。然後通知就只在丟擲這個型別及其子類的異常時才被執行。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 宣告該方法是一個異常通知:在目標方法出現異常時執行此方法 
  3.  * 異常通知可以訪問目標方法中的異常物件,且可以指定在出現特定異常時再執行通知程式碼 
  4.  */  
  5. @AfterThrowing(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))",throwing="e")  
  6. public void afterAllThrowing(JoinPoint joinPoint,Exception e)  
  7. {  
  8.     System.out.println("--afterAllThrowing with throwing------------");  
  9.     System.out.println("Taget method execute exception: " + e);  
  10. }  
  11. /** 
  12.  * 指定在出現特定異常時再執行通知程式碼 
  13.  */  
  14. @AfterThrowing(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))",throwing="e")  
  15. public void afterAllThrowing(JoinPoint joinPoint,NullPointerException e)  
  16. {  
  17.     System.out.println("--afterAllThrowing with NullPointerException------------");  
  18.     System.out.println("Taget method execute exception: " + e);  
  19. }  

環繞通知

環繞通知是所有通知型別中功能最為強大的,能夠全面地控制連線點。甚至可以控制是否執行連線點。對於環繞通知來說,連線點的引數型別必須是 ProceedingJoinPoint 。它是 JoinPoint 的子介面,允許控制何時執行,是否執行連線點。在環繞通知中需要明確呼叫 ProceedingJoinPoint 的 proceed() 方法來執行被代理的方法。如果忘記這樣做就會導致通知被執行了,但目標方法沒有被執行。

注意:環繞通知的方法需要返回目標方法執行之後的結果,即呼叫 joinPoint.proceed()的返回值,否則會出現空指標異常。

Java程式碼  收藏程式碼
  1. /** 
  2.  * 環繞通知需要攜帶ProceedingJoinPoint型別的引數 
  3.  * 環繞通知類似於動態代理的全過程:ProceedingJoinPoint型別的引數可以決定是否執行目標方法 
  4.  * 且環繞通知必須有返回值,返回值即為目標方法的返回值 
  5.  */  
  6. @Around("execution(* xyz.huning.spring4.aop.dao.impl.UserDao.delete(..))")  
  7. public Object around(ProceedingJoinPoint pj)  
  8. {  
  9.     Object result = null;  
  10.     String methodName = pj.getSignature().getName();  
  11.     try{  
  12.         //前置通知  
  13.         System.out.println("The method: " + methodName + "前置通知");  
  14.         //執行目標方法  
  15.         result = pj.proceed();  
  16.         //返回通知  
  17.         System.out.println("The method: " + methodName + "返回通知");  
  18.     }catch(Throwable e)  
  19.     {  
  20.         //異常通知  
  21.         System.out.println("The method: " + methodName + "異常通知: " + e.getMessage());  
  22.     }  
  23.     //後置通知  
  24.     System.out.println("The method: " + methodName + "後置通知");  
  25.     return result;  
  26. }  

指定切面的優先順序

在同一個連線點上應用不止一個切面時,除非明確指定,否則它們的優先順序是不確定的。切面的優先順序可以通過實現 Ordered 介面或利用 @Order 註解指定。實現 Ordered 介面,,getOrder() 方法的返回值越小,優先順序越高。若使用 @Order 註解,序號出現在註解中。

重用切入點定義

在編寫 AspectJ 切面時,可以直接在通知註解中書寫切入點表示式,但同一個切點表示式可能會在多個通知中重複出現。在 AspectJ 切面中,可以通過 @Pointcut 註解將一個切入點宣告成簡單的方法。切入點的方法體通常是空的,因為將切入點定義與應用程式邏輯混在一起是不合理的。切入點方法的訪問控制符同時也控制著這個切入點的可見性。如果切入點要在多個切面中共用,最好將它們集中在一個公共的類中。在這種情況下,它們必須被宣告為 public。在引入這個切入點時,必須將類名也包括在內。如果類沒有與這個切面放在同一個包中,還必須包含包名。其他通知可以通過方法名稱引入該切入點。

Java程式碼  收藏程式碼
  1. /** 
  2.  *  
  3.  * ************重用切點表示式******************************************************************************** 
  4.  *  
  5.  * 定義一個方法,用於宣告切入點表示式,一般的,該方法中不再不要填土其他的程式碼。 
  6.  * 使用@Pointcut來宣告切入點表示式。 
  7.  * 同一個類中其他通知直接使用方法名來引用當前的切入點表示式,如:@Before("method()") 
  8.  * 同一個報下其他類中的通知需要在方法名前加類名,如:@Before("class.method()") 
  9.  * 其他包下面類中的通知需要在方法名前加類的全額限定名,如:@AfterReturning(value="package.class.method()",returning="result") 
  10.  *  
  11.  * 第一個星號代表匹配任意修飾符及任意返回值, 第二個星號表示任意方法名稱,引數列表中的兩個點號表示任意數量和型別的引數 
  12.  */  
  13. @Pointcut("execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))")  
  14. public void userDaoJoinPoint(){}  

原文:http://ihuning.iteye.com/blog/2227027

相關推薦

Spring4AOP註解配置

啟動AOP配置 要在 Spring 應用中使用 AspectJ 註解,需要如下支援: 1. 在 classpath 下包含 AspectJ 類庫:aopalliance.jar、aspectj.weaver.jar 和 spring-aspects.jar 2.

SpringMVC原理及非註解配置

ges 控制器 sof 靈活 size 實現 query -c requests 1. Spring介紹   Spring MVC是Spring提供的一個強大而靈活的web框架。借助於註解,Spring MVC提供了幾乎是POJO的開發模式,使得控制器的開發和測試更加簡單

Spring Boot中使用MyBatis註解配置(1)

sql type .org 實體 sch 整合 PE 匯總 同傳 之前在Spring Boot中整合MyBatis時,采用了註解的配置方式,相信很多人還是比較喜歡這種優雅的方式的,也收到不少讀者朋友的反饋和問題,主要集中於針對各種場景下註解如何使用,下面就對幾種常見的情況舉

Mysqlmy.cnf配置

線程池 ext 自動刪除 statement arr 網絡 決定 而不是 amp Mysql之my.cnf配置詳解 mysql5.6的版本有400多個變量可以配置,可以通過下列命令獲得mysql> show variables; 配置文件參數如下: #客戶端設置,即

springboot中使用Mybatis註解配置

版權宣告:本文為博主原創文章,未經博主允許不得轉載。    https://blog.csdn.net/Winter_chen001/article/details/78623700 之前寫了關於Spring boot Mybatis 整合(註解版) 中使用了簡單的註解

Struts學習Message Resources配置

目錄 一、概述 二、用法 三、建立資源包 四、配置 五、資原始檔放在哪裡 六、Tags 七、Actions 八、國際化 九、JSTL 十、結論 一、概述        Message Resources訊息

Spring Boot中使用MyBatis註解配置

   轉自翟永超 之前在Spring Boot中整合MyBatis時,採用了註解的配置方式,相信很多人還是比較喜歡這種優雅的方式的,也收到不少讀者朋友的反饋和問題,主要集中於針對各種場景下註解如何使用,下面就對幾種常見的情況舉例說明用法。 在做下面的示例之前,先準備一

Spring4.IoC容器bean配置

之前在有簡單的配置過bean,在bean的配置中有多種配置方式,下面一一介紹。 bean的配置方式      1.通過全類名(反射)      2.通過工廠方法(靜態工廠方法&例項工廠方法)      3.FactoyBean 通過全類名方式 配置Bean &

mavensetting.xml 配置

檔案存放位置 全域性配置: ${M2_HOME}/conf/settings.xml 使用者配置: ${user.home}/.m2/settings.xml note:使用者配置優先於全域性配置。${user.home} 和和所有其他系統屬性只能在3.0+版本上

【專案管理】Mybatis-Generator最完美配置

 小夥伴們注意了,全哥花了一些時間,重新整理了一個最完美的Mybatis Generator(簡稱MBG)配置檔案詳細說明,老闆再也不用擔心我的學習!!! 不用多說,直接上程式碼: <?xml

Antbuild.xml配置

前言 國內關於build.xml的配置資料太零散了,實在是受不了,故而將自己的筆記整理成博文,方便大家查閱和理解。 build.xml配置引數 構建檔案預設叫build.xml,其有很多配置引數。 project 每個構建檔案都有一個project標籤,有以下屬性:

MyBatis原始碼分析@SelectProvider註解使用

MyBatis原始碼分析之@SelectProvider註解使用詳解 之前講了MyBatis的配置、plugin、Select查詢,還有@MapKey註解的使用與原理,還有返回@ResultMap等等,我原想直接從MyBatis的快取開始說起,但是想想還是得說一下MyBatis中的@

Apache2.4httpd.conf配置

常用配置項:使用httpd-vhosts.conf,開啟虛擬主機:Include "conf/extra/httpd-vhosts.conf"前面的註釋,表示開啟虛擬主機1)ServerRoot 根路徑2)Listen  指定伺服器監聽的ip和埠3)LoadModule  A

《Java Spring框架》Spring切面(AOP配置

1.  Spring 基本概念 AOP(Aspect Oriented Programming)稱為面向切面程式設計,在程式開發中主要用來解決一些系統層面上的問題,比如日誌,事務,許可權等待,Struts2的攔截器設計就是基於AOP的思想,是個比較經典的例子。 在不改變原有的邏輯的基礎

spring AOP解析註解方式

parser 分享 pro asp mes aop log space spec 命名空間處理器是AopNamespaceHandler,我們可以看到這裏註冊了幾個解析器,第一個我們知道是xml形式的解析,接下來我們看AspectJAutoProxyBeanDefiniti

Java程式設計師從笨鳥到菜鳥(七十二)細談Spring(四)利用註解實現spring基本配置

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Java程式設計師從笨鳥到菜鳥(七十四)細談Spring(六)springAOP基本概念和配置

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!                       首先我們來看一下官方文件所給我們的關於AOP的一些概念性詞語的解釋:切面(Aspect):一個關注點的模組化,這個關注點可能會橫切多個物件。事務管

Spring aop 配置註解

Spring aopaop:(Aspect Oriented Programming)面向切面程式設計,縱向重複,橫向抽取 代理: 生活中的例項:找明星拍戲,上綜藝。拍戲   直接找明星,說明明星太小。如果明星有點名氣,那就不能直接訪問了,必須先通過先訪問明星的經紀人,然後由

Web.xml配置context-param

ltr 完成 數據庫 數據 鍵值對 art str htm 方法 轉自:http://blog.csdn.net/liaoxiaohua1981/article/details/6759206 格式定義: [html] view plaincopy

SpringMVC 框架系列組件概述與配置

align 概述 handle ont htm 配置文件 掃描器 springmvc 解析 在上一篇文章 SpringMVC 框架系列之初識與入門實例 的實例中,我們已經知道,SpringMVC 框架是一個 web 層的框架,本篇文章就詳細解釋一下 SpringMVC 框架