欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用Spring開啟注解AOP的支持放置的位置

 更新時間:2021年09月30日 16:06:40   作者:JSON_ZJS  
這篇文章主要介紹了使用Spring開啟注解AOP的支持放置的位置,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Spring開啟注解AOP的支持放置的位置

放在springmvc的aop,需要在springmvc的配置文件中寫開啟aop,而不是spring的配置文件

最近使用aop來記錄controller的日志.

但是發(fā)現(xiàn)沒有起作用.

后來發(fā)現(xiàn)是因為我的 aop 是寫在controller層(在springmvc的容器中 -web中)

而開啟aop配置卻寫在spring(applicationContext.xml)中

所以不起作用,需要在springmvc.xml的配置文件中也開啟才行

Spring 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 創(chuàng)建代理。

用 AspectJ 注解聲明切面

要在 Spring 中聲明 AspectJ 切面,只需要在 IOC 容器中將切面聲明為 Bean 實例。當在 Spring IOC 容器中初始化 AspectJ 切面之后,Spring IOC 容器就會為那些與 AspectJ 切面相匹配的 Bean 創(chuàng)建代理。

在 AspectJ 注解中,切面只是一個帶有 @Aspect 注解的 Java 類。通知是標注有某種注解的簡單的 Java 方法。

AspectJ 支持 5 種類型的通知注解:

  • @Before:前置通知,在方法執(zhí)行之前執(zhí)行
  • @After:后置通知,在方法執(zhí)行之后執(zhí)行
  • @AfterRunning:返回通知,在方法返回結果之后執(zhí)行
  • @AfterThrowing:異常通知,在方法拋出異常之后
  • @Around:環(huán)繞通知,圍繞著方法執(zhí)行

前置通知

前置通知:在方法執(zhí)行之前執(zhí)行的通知。

前置通知使用 @Before 注解,并將切入點表達式的值作為注解值。

/**
 * 把這個類聲明為一個切面:
 * 1. 使用注解“@Repository”把該類放入到IOC容器中
 * 2. 使用注解“@Aspect”把該類聲明為一個切面
 * 
 * 設置切面的優(yōu)先級:
 * 3. 使用注解“@Order(number)”指定前面的優(yōu)先級,值越小,優(yōu)先級越高
 */
@Order(1)
@Aspect
@Repository
public class DaoLogAspect {
 /**
  * 聲明該方法是一個前置通知:在目標方法開始之前執(zhí)行
  * '@Before'標識這個方法是個前置通知,切點表達式表示執(zhí)行 UserDao類的 insert(User user) 方法.
  */
 @Before("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")
 public void beforeInsert()
 {
  System.out.println("--beforeInsert------------");
 }
}

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

最典型的切入點表達式是根據(jù)方法的簽名來匹配各種方法:

  • execution * xyz.huning.spring4.aop.dao.impl.UserDao.*(..):匹配UserDao中聲明的所有方法,第一個 * 代表任意修飾符及任意返回值。第二個 * 代表任意方法。 .. 匹配任意數(shù)量的參數(shù)。若目標類與接口與該切面在同一個包中,可以省略包名。
  • execution public * UserDao.*(..):匹配 UserDao類的所有公有方法。
  • execution public double UserDao.*(..):匹配 UserDao中返回 double 類型數(shù)值的方法。
  • execution public double UserDao.*(double, ..):匹配第一個參數(shù)為 double 類型的方法, .. 匹配任意數(shù)量任意類型的參數(shù)。
  • execution public double UserDao.*(double,double):匹配參數(shù)類型為 double,double 類型的方法。

合并切入點表達式

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

 /**
  * 合并切入點表達式
  * 在 AspectJ 中,切入點表達式可以通過操作符 &&,||,! 結合起來。
  */
 @Pointcut("execution(* *.insert(..)) || execution(* *.delete(..))")
 public void insertDeleteJoinPoint(){}

讓通知訪問當前連接點的細節(jié)

可以在通知方法中聲明一個類型為 JoinPoint 的參數(shù)。然后就能訪問鏈接細節(jié)。如方法名稱和參數(shù)值。

 /**
  * 聲明該方法是一個前置通知:在目標方法開始之前執(zhí)行
  */
 @Before("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")
 public void beforeInsert(JoinPoint joinPoint)
 {
  System.out.println("--beforeInsert with joinPoint------------");
  //獲取方法名稱
  String methodName = joinPoint.getSignature().getName();
  //獲取參數(shù)值
  String args = Arrays.toString(joinPoint.getArgs());
  System.out.println("Taget method: " + methodName);
  System.out.println("Taget method args: " + args);
 }

后置通知

后置通知是在連接點完成之后執(zhí)行的, 即連接點返回結果或者拋出異常的時候,下面的后置通知記錄了方法的終止。

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

 /**
  * 聲明該方法是一個后置通知:在目標方法開始之后執(zhí)行(即使目標方法執(zhí)行出現(xiàn)異常也會執(zhí)行)
  * 后置通知中不能訪問目標方法的執(zhí)行結果
  */
 @After("execution(public xyz.huning.spring4.aop.dao.User xyz.huning.spring4.aop.dao.impl.UserDao.insert(xyz.huning.spring4.aop.dao.User))")
 public void afterInsert()
 {
  System.out.println("--afterInsert------------");
 }

返回通知

無論連接點是正常返回還是拋出異常,后置通知都會執(zhí)行。如果只想在連接點返回的時候記錄日志,應使用返回通知代替后置通知。在返回通知中,只要將 returning 屬性添加到 @AfterReturning 注解中,就可以訪問連接點的返回值。該屬性的值即為用來傳入返回值的參數(shù)名稱。

必須在通知方法的簽名中添加一個同名參數(shù)。在運行時,Spring AOP 會通過這個參數(shù)傳遞返回值。原始的切點表達式需要出現(xiàn)在 pointcut 屬性中。

 /**
  * 聲明該方法是一個返回通知:在目標方法正常結束之后返回(目標方法執(zhí)行出現(xiàn)異常時不再執(zhí)行)
  * 返回通知可以訪問目標方法的執(zhí)行結果
  */
 @AfterReturning(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.query(..))",returning="result")
 public void afterQueryReturning(JoinPoint joinPoint,Object result)
 {
  System.out.println("--afterQueryReturning with joinPoint and result------------");
  String methodName = joinPoint.getSignature().getName();
  String args = Arrays.toString(joinPoint.getArgs());
  System.out.println("Taget method: " + methodName);
  System.out.println("Taget method args: " + args);
  System.out.println("Taget method execute result: " + result);
 }

異常通知

只在連接點拋出異常時才執(zhí)行異常通知,將 throwing 屬性添加到 @AfterThrowing 注解中,也可以訪問連接點拋出的異常。Throwable 是所有錯誤和異常類的超類。

所以在異常通知方法可以捕獲到任何錯誤和異常。如果只對某種特殊的異常類型感興趣,可以將參數(shù)聲明為其他異常的參數(shù)類型。然后通知就只在拋出這個類型及其子類的異常時才被執(zhí)行。

 /**
  * 聲明該方法是一個異常通知:在目標方法出現(xiàn)異常時執(zhí)行此方法
  * 異常通知可以訪問目標方法中的異常對象,且可以指定在出現(xiàn)特定異常時再執(zhí)行通知代碼
  */
 @AfterThrowing(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))",throwing="e")
 public void afterAllThrowing(JoinPoint joinPoint,Exception e)
 {
  System.out.println("--afterAllThrowing with throwing------------");
  System.out.println("Taget method execute exception: " + e);
 }
 
 /**
  * 指定在出現(xiàn)特定異常時再執(zhí)行通知代碼
  */
 @AfterThrowing(value="execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))",throwing="e")
 public void afterAllThrowing(JoinPoint joinPoint,NullPointerException e)
 {
  System.out.println("--afterAllThrowing with NullPointerException------------");
  System.out.println("Taget method execute exception: " + e);
 }

環(huán)繞通知

環(huán)繞通知是所有通知類型中功能最為強大的,能夠全面地控制連接點。甚至可以控制是否執(zhí)行連接點。對于環(huán)繞通知來說,連接點的參數(shù)類型必須是 ProceedingJoinPoint 。

它是 JoinPoint 的子接口,允許控制何時執(zhí)行,是否執(zhí)行連接點。在環(huán)繞通知中需要明確調用 ProceedingJoinPoint 的 proceed() 方法來執(zhí)行被代理的方法。如果忘記這樣做就會導致通知被執(zhí)行了,但目標方法沒有被執(zhí)行。

注意:環(huán)繞通知的方法需要返回目標方法執(zhí)行之后的結果,即調用 joinPoint.proceed()的返回值,否則會出現(xiàn)空指針異常。

 /**
  * 環(huán)繞通知需要攜帶ProceedingJoinPoint類型的參數(shù)
  * 環(huán)繞通知類似于動態(tài)代理的全過程:ProceedingJoinPoint類型的參數(shù)可以決定是否執(zhí)行目標方法
  * 且環(huán)繞通知必須有返回值,返回值即為目標方法的返回值
  */
 @Around("execution(* xyz.huning.spring4.aop.dao.impl.UserDao.delete(..))")
 public Object around(ProceedingJoinPoint pj)
 {
     Object result = null;
     String methodName = pj.getSignature().getName();
     
     try{
      //前置通知
      System.out.println("The method: " + methodName + "前置通知");
      //執(zhí)行目標方法
      result = pj.proceed();
      //返回通知
      System.out.println("The method: " + methodName + "返回通知");
     }catch(Throwable e)
     {
      //異常通知
      System.out.println("The method: " + methodName + "異常通知: " + e.getMessage());
     }
     //后置通知
     System.out.println("The method: " + methodName + "后置通知");
     
     return result;
 }

指定切面的優(yōu)先級

在同一個連接點上應用不止一個切面時,除非明確指定,否則它們的優(yōu)先級是不確定的。

切面的優(yōu)先級可以通過實現(xiàn) Ordered 接口或利用 @Order 注解指定。實現(xiàn) Ordered 接口,,getOrder() 方法的返回值越小,優(yōu)先級越高。若使用 @Order 注解,序號出現(xiàn)在注解中。

重用切入點定義

在編寫 AspectJ 切面時,可以直接在通知注解中書寫切入點表達式,但同一個切點表達式可能會在多個通知中重復出現(xiàn)。

在 AspectJ 切面中,可以通過 @Pointcut 注解將一個切入點聲明成簡單的方法。切入點的方法體通常是空的,因為將切入點定義與應用程序邏輯混在一起是不合理的。

切入點方法的訪問控制符同時也控制著這個切入點的可見性。如果切入點要在多個切面中共用,最好將它們集中在一個公共的類中。在這種情況下,它們必須被聲明為 public。

在引入這個切入點時,必須將類名也包括在內。如果類沒有與這個切面放在同一個包中,還必須包含包名。其他通知可以通過方法名稱引入該切入點。

 /**
  * 
  * ************重用切點表達式********************************************************************************
  * 
  * 定義一個方法,用于聲明切入點表達式,一般的,該方法中不再不要填土其他的代碼。
  * 使用@Pointcut來聲明切入點表達式。
  * 同一個類中其他通知直接使用方法名來引用當前的切入點表達式,如:@Before("method()")
  * 同一個報下其他類中的通知需要在方法名前加類名,如:@Before("class.method()")
  * 其他包下面類中的通知需要在方法名前加類的全額限定名,如:@AfterReturning(value="package.class.method()",returning="result")
  * 
  * 第一個星號代表匹配任意修飾符及任意返回值, 第二個星號表示任意方法名稱,參數(shù)列表中的兩個點號表示任意數(shù)量和類型的參數(shù)
  */
 @Pointcut("execution(* xyz.huning.spring4.aop.dao.impl.UserDao.*(..))")
 public void userDaoJoinPoint(){}
 

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • Java的運算符和程序邏輯控制你了解嗎

    Java的運算符和程序邏輯控制你了解嗎

    這篇文章主要為大家詳細介紹了Java的運算符和程序邏輯控制,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-03-03
  • 淺談java對象的比較

    淺談java對象的比較

    這篇文章主要給大家分享java對象的比較,主要有元素的比較、類的比較及比較的方法,想具體了解的小伙伴和小編一起進入下面文章內容吧
    2021-10-10
  • mybatis攔截器實現(xiàn)通用權限字段添加的方法

    mybatis攔截器實現(xiàn)通用權限字段添加的方法

    這篇文章主要給大家介紹了關于mybatis攔截器實現(xiàn)通用權限字段添加的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mybatis具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • java.lang.FileNotFoundException 異常的正確解決方法(親測有效)

    java.lang.FileNotFoundException 異常的正確解決方法(親測有效)

    java.io.FileNotFoundException是一個在文件操作過程中常見的異常,它屬于IOException的一個子類,這篇文章主要介紹了java.lang.FileNotFoundException 異常的正確解決方法(親測有效),需要的朋友可以參考下
    2024-01-01
  • Java幸運28系統(tǒng)搭建數(shù)組的使用實例詳解

    Java幸運28系統(tǒng)搭建數(shù)組的使用實例詳解

    在本篇文章里小編給大家整理了關于Java幸運28系統(tǒng)搭建數(shù)組的使用實例內容,有需要的朋友們可以參考學習下。
    2019-09-09
  • 解決mybatisplus的分頁插件和條件構造器自定義SQL遇到的BUG

    解決mybatisplus的分頁插件和條件構造器自定義SQL遇到的BUG

    這篇文章主要介紹了解決mybatisplus的分頁插件和條件構造器自定義SQL遇到的BUG,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot 創(chuàng)建web項目并部署到外部Tomcat

    SpringBoot 創(chuàng)建web項目并部署到外部Tomcat

    本篇文章主要介紹了SpringBoot 創(chuàng)建web項目并部署到外部Tomcat,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • request.getParameter()方法的簡單理解與運用方式

    request.getParameter()方法的簡單理解與運用方式

    在JavaWeb開發(fā)中,request對象扮演著至關重要的角色,它是HTTP請求的封裝,request.getParameter()用于獲取客戶端通過GET或POST方式發(fā)送的參數(shù),與之相對,request.setAttribute()用于在服務器端設置屬性,這些屬性只在一次請求中有效
    2024-10-10
  • Seata?AT模式啟動過程圖文示例詳解

    Seata?AT模式啟動過程圖文示例詳解

    這篇文章主要為大家介紹了Seata?AT模式啟動過程圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • java判斷中文字符串長度的簡單實例

    java判斷中文字符串長度的簡單實例

    下面小編就為大家?guī)硪黄猨ava判斷中文字符串長度的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01

最新評論