一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringAOP四種通知類型+環繞通知說明

SpringAOP四種通知類型+環繞通知說明

2021-12-22 11:04晚點喝可樂z Java教程

這篇文章主要介紹了SpringAOP四種通知類型+環繞通知說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

SpringAOP的四種通知類型:前置通知、異常通知、后置通知、異常通知

 

一、四種常見的通知類型

給出 賬戶的業務層接口 IAccountService.java,

為了便于演示這四種通知類型,我們就只留下了一個方法。

public interface IAccountService {
 void saveAccount();
}

給出 賬戶的業務層接口的實現類 AccountServiceImpl.java

public class AccountServiceImpl implements IAccountService{
  @Override
  public void saveAccount() {
      System.out.println("執行了保存");
      //int i=1/0;
  }
}

給出一個日志類, 用于打印日志

public class Logger {
  /**
   * 前置通知
   */
  public  void beforePrintLog(){
      System.out.println("前置通知Logger類中的beforePrintLog方法開始記錄日志了。。。");
  }
  /**
   * 后置通知
   */
  public  void afterReturningPrintLog(){
      System.out.println("后置通知Logger類中的afterReturningPrintLog方法開始記錄日志了。。。");
  }
  /**
   * 異常通知
   */
  public  void afterThrowingPrintLog(){
      System.out.println("異常通知Logger類中的afterThrowingPrintLog方法開始記錄日志了。。。");
  }
  /**
   * 最終通知
   */
  public  void afterPrintLog(){
      System.out.println("最終通知Logger類中的afterPrintLog方法開始記錄日志了。。。");
  }
}

給出配置信息bean.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd">
  <!-- 配置srping的Ioc,把service對象配置進來-->
  <bean id="accountService" class="service.AccountServiceImpl"></bean>
  <!-- 配置Logger類 -->
  <bean id="logger" class="utils.Logger"></bean>
  <!--配置AOP-->
  <aop:config>
    <!--配置切入點表達式 -->
      <aop:pointcut id="pt1" expression="execution(* service.AccountServiceImpl.saveAccount())"></aop:pointcut>
      <!--配置切面 -->
      <aop:aspect id="logAdvice" ref="logger">
          <!-- 配置前置通知:在切入點方法執行之前執行-->
          <aop:before method="beforePrintLog" pointcut-ref="pt1" ></aop:before>
          <!-- 配置后置通知:在切入點方法正常執行之后值-->
          <aop:after-returning method="afterReturningPrintLog" pointcut-ref="pt1"></aop:after-returning>
          <!-- 配置異常通知:在切入點方法執行產生異常之后執行-->
          <aop:after-throwing method="afterThrowingPrintLog" pointcut-ref="pt1"></aop:after-throwing>
          <!-- 配置最終通知:無論切入點方法是否正常執行它都會在其后面執行-->
          <aop:after method="afterPrintLog" pointcut-ref="pt1"></aop:after>
          
      </aop:aspect>
  </aop:config>
</beans>

注意

1)異常通知和后置通知永遠只能執行一個

2)配置切入點表達式

此標簽寫在aop:aspect標簽內部只能當前切面使用。

它還可以寫在aop:aspect外面,此時就變成了所有切面可用

給出Test類

public class AOPTest {
  public static void main(String[] args) {
      //1.獲取容器
      ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
      //2.獲取對象
      IAccountService as = (IAccountService)ac.getBean("accountService");
      //3.執行方法
     as.saveAccount();
  }
}

執行結果:

SpringAOP四種通知類型+環繞通知說明

當我們放開AccountServiceImpl類中我們故意制造的異常 int i=1/0;時:

SpringAOP四種通知類型+環繞通知說明

 

二、環繞通知

環繞通知,只需要稍稍微改變上面例子的兩點即可

1、改動日志類 Logger.java

public class Logger {
  public Object aroundPringLog(ProceedingJoinPoint pjp){
      Object rtValue = null;
      try{
          Object[] args = pjp.getArgs();//得到方法執行所需的參數
          System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。前置");
          rtValue = pjp.proceed(args);//明確調用業務層方法(切入點方法)
          System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。后置");
          return rtValue;
      }catch (Throwable t){
          System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。異常");
          throw new RuntimeException(t);
      }finally {
          System.out.println("Logger類中的aroundPringLog方法開始記錄日志了。。。最終");
      }
  }
}

注意:pjp.proceed(args)會報異常,必須用 Throwable t,因為Exception攔不住它

2、改動配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/aop
      http://www.springframework.org/schema/aop/spring-aop.xsd">
  <!-- 配置srping的Ioc,把service對象配置進來-->
  <bean id="accountService" class="service.AccountServiceImpl"></bean>
  <!-- 配置Logger類 -->
  <bean id="logger" class="utils.Logger"></bean>
  <!--配置AOP-->
  <aop:config>
  	<!--配置切入點表達式 -->
      <aop:pointcut id="pt1" expression="execution(* service.AccountServiceImpl.saveAccount())"></aop:pointcut>
      <!--配置切面 -->
      <aop:aspect id="logAdvice" ref="logger">
          <!-- 配置環繞通知 詳細的注釋請看Logger類中-->
          <aop:around method="aroundPringLog" pointcut-ref="pt1"></aop:around>
      </aop:aspect>
  </aop:config>
</beans>

分析

  • spring中的環繞通知是spring框架為我們提供的一種可以在代碼中手動控制增強方法何時執行的方式。
  • Spring框架為我們提供了一個接口:ProceedingJoinPoint。該接口有一個方法proceed(),此方法就相當于明確調用切入點方法。該接口可以作為環繞通知的方法參數,在程序執行時,spring框架會為我們提供該接口的實現類供我們使用。

 

AOP機制之環繞通知的見解

我們都知道,AOP機制的核心是在不修改源碼的基礎上對業務層方法的增強。

其中有五個通知類型

  • 1、前置通知:在切入點方法之前執行
  • 2、后置通知:在切入點方法之后通知
  • 3、異常通知:在執行切入點方法過程中出現異常后執行(因此異常通知和后置通知只能執行一個)
  • 4、最終通知:無論切入點方法是否正常執行它都會執行
  • 5、環繞通知: 當配置環繞通知之后,在環繞通知里面必須要明確調用業務層的方法,如果不調用,就會出現只出現通知,而不執行方法。其中原理和動態代理是一樣的,代碼如下。
public AccountService getAccountService() {
      return (AccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
          @Override
          public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
              Object rtValue=null;
              try {
                  //1、開啟事務
                  txManager.beginTransaction();
                  //2、執行操作,整個過程像對每個方法進行了包裝,并返回新的accountService對象
                  rtValue=method.invoke(accountService,objects);
                  //3、提交事務
                  txManager.commit();
                  //4、返回結果
                  return rtValue;
              }catch (Exception e){
                  //5、回滾事務
                  txManager.rollback();
                  throw new RuntimeException(e);
              }finally {
                  //6、釋放連接
                  txManager.release();
              }
          }
      });
  }

如果不明確調用業務層方法,就像一個畫皮,沒有發揮本質的作用。

除此之外,我認為環繞通知可以代替其他的四個通知,

public Object aroundPrintLog(ProceedingJoinPoint pjp){//環繞通知是不是能夠代替其他的通知
      Object rtvalue=null;
      try {
          /**
           *這里的一切都是為都是給業務層方法進行增強,例如:把那些方法拿過來,然后核心的還是rtvalue=pjp.proceed(args),
           *其他的輸出只不過是為核心的業務層方法進行修飾
           */
          Object[] args=pjp.getArgs();//得到方法執行所需的參數
          System.out.println("前置通知");
          rtvalue=pjp.proceed(args);//明確調用業務層方法
          System.out.println("后置通知");
          return rtvalue;
      }catch (Throwable e){
          System.out.println("異常通知");
          throw new RuntimeException(e);
      }finally {
          System.out.println("最終通知");
      }
  }

這個屬于典型的環繞通知,其中把輸出方法換成相應的通知方法就可以(有不同觀點的可以說出來一起討論)。

最后,分享一下我學這個知識的方法。方法增強,本質上就是對源碼不修改的情況下進行方法的加工。就好像烤羊肉串一樣,其中的核心就是羊肉,就像公司給你的業務層方法(這個是不讓修改的)。在給顧客使用前,收先對羊肉進行刷油、烤、撒料一系列過程,這一過程就是我們對業務層方法的增強,使業務層的功能更加健壯,對應的燒烤也就是更美味。核心的一點就是正確調用業務層的方法,不管在哪類通知中,都能對業務層方法進行正確、有效地增強

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/qq_41949320/article/details/106841824

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
主站蜘蛛池模板: 国产精品一区二区三区久久 | 免费网址在线观看入口推荐 | 青青青青久久国产片免费精品 | 大团圆免费阅读全文 | 久久国产免费 | 521色香蕉网站在线观看 | 91国产高清 | 欧美精品一区二区三区久久 | 91尤物在线| 国产老村长足疗店对白 | 久久这里只精品国产99re66 | 美女叽叽 | 欧洲男同直粗无套播放视频 | 男女一级特黄a大片 | 久久久久琪琪精品色 | 青青色在线 | 爽好舒服快想要免费看 | 天美视频在线 | 成人男女啪啪免费观看网站 | 欧美一级高清免费a | 免费看3d小舞被躁视频网站 | 日韩性生活片 | 国产精品aⅴ| 欧美人shou交在线播放 | 色综色天天综合网 | 美女女女女女女bbbbbb毛片 | 韩国久播影院理论片不卡影院 | 深夜日韩 | 亚洲国产成人99精品激情在线 | 毛片 ftp| 国产一久久香蕉国产线看观看 | 古装床戏做爰无遮挡三级 | 国内揄拍国内精品久久 | 99久久国产综合精品1尤物 | 日本高清视频网站 | 奇米影视777最新在线 | 国产成人在线综合 | 国产乱码一卡二卡3卡四卡 国产乱插 | 男女一级簧色带 | 公园吃女人奶野战视频 | 肥胖女性大bbbbbb视频女厕 |