日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring AOP 五大通知类型

發布時間:2023/12/20 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring AOP 五大通知类型 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.前置通知

在目標方法執行之前執行執行的通知。

前置通知方法,可以沒有參數,也可以額外接收一個JoinPoint,Spring會自動將該對象傳入,代表當前的連接點,通過該對象可以獲取目標對象 和 目標方法相關的信息

注意,如果接收JoinPoint,必須保證其為方法的第一個參數,否則報錯。

配置方式:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-3.2.xsd"><context:annotation-config></context:annotation-config><context:component-scan base-package="cn.tedu.service,cn.tedu.aop"></context:component-scan><aop:config proxy-target-class="true"><!-- 配置切入點 --><aop:pointcut expression="execution(* cn.tedu.service.UserServiceImpl.addUser(..))" id="pc01"/><!-- 配置切面 --><aop:aspect ref="firstAspect">
       <<!-- 前置通知 -->
<aop:before method="before" pointcut-ref="pc01"/></aop:aspect></aop:config> </beans> package cn.tedu.service;import org.springframework.stereotype.Service; /*** UserServiceImple:目標對象*/ @Service("userService") public class UserServiceImple implements UserService {@Overridepublic void addUser(String name) {System.out.println("增加用戶。。");}@Overridepublic void updateUser() {System.out.println("修改用戶。。");}@Overridepublic void deleteUser() {System.out.println("刪除用戶。。");}@Overridepublic void query() {System.out.println("查詢用戶。。");} } package cn.tedu.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.springframework.stereotype.Component; /*** FirstAspect:切面代碼*/ @Component public class FirstAspect {public void before(JoinPoint jp){ // 可以選擇額外的傳入一個JoinPoint連接點對象,必須用方法的第一個參數接收。Class clz = jp.getTarget().getClass();Signature signature = jp.getSignature(); // 通過JoinPoint對象獲取更多信息String name = signature.getName();System.out.println("1 -- before...["+clz+"]...["+name+"]...");} } package cn.tedu.test;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.tedu.service.UserService; /*** AOPTest:測試代碼*/ public class AOPTest {@Testpublic void test01(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) context.getBean("userService");userService.addUser("cjj"); // 一個連接點 } }

執行結果:

1 -- before...[class cn.tedu.service.UserServiceImple]...[addUser]... 增加用戶。。

2.環繞通知

在目標方法執行之前和之后都可以執行額外代碼的通知。

在環繞通知中必須顯式的調用目標方法,目標方法才會執行,這個顯式調用時通過ProceedingJoinPoint來實現的,可以在環繞通知中接收一個此類型的形參,spring容器會自動將該對象傳入,注意這個參數必須處在環繞通知的第一個形參位置

**要注意,只有環繞通知可以接收ProceedingJoinPoint,而其他通知只能接收JoinPoint

環繞通知需要返回返回值,否則真正調用者將拿不到返回值,只能得到一個null

環繞通知有控制目標方法是否執行、有控制是否返回值、有改變返回值的能力。

環繞通知雖然有這樣的能力,但一定要慎用,不是技術上不可行,而是要小心不要破壞了軟件分層的“高內聚 低耦合”的目標。

配置方式:

<!-- 環繞通知 --><aop:around method="around" pointcut-ref="pc1"/> public Object around(ProceedingJoinPoint jp) throws Throwable{System.out.println("1 -- around before...");Object obj = jp.proceed(); //--顯式的調用目標方法System.out.println("1 -- around after...");return obj;}

運行結果:

1 -- around before... 增加用戶。。 1 -- around after...

3.后置通知

在目標方法執行之后執行的通知。

在后置通知中也可以選擇性的接收一個JoinPoint來獲取連接點的額外信息,但是這個參數必須處在參數列表的第一個

?配置方式:

<!-- 后置通知 --> <aop:after-returning method="afterReturn" pointcut-ref="pc1"/> public void afterReturn(JoinPoint jp){Class clz = jp.getTarget().getClass();Signature signature = jp.getSignature(); String name = signature.getName();System.out.println("1 -- afterReturn...["+clz+"]...["+name+"]...");}

執行結果:

1 -- before...[class cn.tedu.service.UserServiceImple]...[addUser]... 1 -- around before... 增加用戶。。 1 -- around after... 1 -- afterReturn...[class cn.tedu.service.UserServiceImple]...[addUser]...

在后置通知中,還可以通過配置獲取返回值

一定要保證JoinPoint處在參數列表的第一位,否則拋異常

配置方式:

<!-- 后置通知 --> <aop:after-returning method="afterReturn" pointcut-ref="pc1" returning="msg"/> public void afterReturn(JoinPoint jp, Object msg){Class clz = jp.getTarget().getClass();Signature signature = jp.getSignature(); String name = signature.getName();System.out.println("1 -- afterReturn...["+clz+"]...["+name+"]...["+msg+"]...");}

執行結果:

1 -- before...[class cn.tedu.service.UserServiceImple]...[addUser]... 1 -- around before... 增加用戶。。 1 -- around after... 1 -- afterReturn...[class cn.tedu.service.UserServiceImple]...[addUser]...[cjj]...

4.異常通知

在目標方法拋出異常時執行的通知

可以配置傳入JoinPoint獲取目標對象和目標方法相關信息,但必須處在參數列表第一位

另外,還可以配置參數,讓異常通知可以接收到目標方法拋出的異常對象。

配置方法:

<!-- 異常通知 --> <aop:after-throwing method="afterThrow" pointcut-ref="pc1" throwing="e"/> public void afterThrow(JoinPoint jp,Throwable e){Class clz = jp.getTarget().getClass();String name = jp.getSignature().getName();System.out.println("1afterThrow..["+clz+"]..["+name+"].."+e.getMessage());}

代碼報異常后

執行結果:

1 -- before...[class cn.tedu.service.UserServiceImple]...[addUser]... 1 -- around before... 1 -- afterThrow..[class cn.tedu.service.UserServiceImple]..[addUser]../ by zero

5.最終通知

是在目標方法執行之后執行的通知

和后置通知不同之處在于,后置通知是在方法正常返回后執行的通知,如果方法沒有正常返-例如拋出異常,則后置通知不會執行。

最終通知無論如何都會在目標方法調用過后執行,即使目標方法沒有正常的執行完成

另外,后置通知可以通過配置得到返回值,而最終通知無法得到。

最終通知也可以額外接收一個JoinPoint參數,來獲取目標對象和目標方法相關信息,但一定要保證必須是第一個參數

配置方式:

<!-- 最終通知 --> <aop:after method="after" pointcut-ref="pc1" /> public void after(JoinPoint jp){Class clz = jp.getTarget().getClass();String name = jp.getSignature().getName();System.out.println("1 -- after..["+clz+"]..["+name+"]...");}

執行結果:

1 -- before...[class cn.tedu.service.UserServiceImple]...[addUser]... 1 -- around before... 增加用戶。。 1 -- around after... 1 -- afterReturn...[class cn.tedu.service.UserServiceImple]...[addUser]...[cjj]... 1 -- after..[class cn.tedu.service.UserServiceImple]..[addUser]... cjj

源碼

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd "><context:annotation-config></context:annotation-config><context:component-scan base-package="cn.tedu.service,cn.tedu.aop"></context:component-scan><!-- proxy-target-class屬性值決定是基于接口的還是基于類的代理被創建 --><aop:config proxy-target-class="true"> <!-- 配置切入點 --><aop:pointcut expression="execution(* cn.tedu.service.UserServiceImple.addUser(..))" id="pc1"/> <!-- 配置切入面 --><aop:aspect ref="firstAspect"><!-- 前置通知 --> <aop:before method="before" pointcut-ref="pc1"/><!-- 環繞通知 --><aop:around method="around" pointcut-ref="pc1"/><!-- 后置通知 --><!-- <aop:after-returning method="afterReturn" pointcut-ref="pc1"/> --><aop:after-returning method="afterReturn" pointcut-ref="pc1" returning="msg"/><!-- 異常通知 --><aop:after-throwing method="afterThrow" pointcut-ref="pc1" throwing="e"/><!-- 最終通知 --><aop:after method="after" pointcut-ref="pc1" /></aop:aspect></aop:config></beans> applicationContext.xml package cn.tedu.service; /*** 接口*/ public interface UserService {public String addUser(String name);public void updateUser();public void deleteUser();public void query(); } UserService.java package cn.tedu.service;import org.springframework.stereotype.Service; /*** UserServiceImple:目標對象*/ @Service("userService") public class UserServiceImple implements UserService {@Overridepublic String addUser(String name) {// int i = 1/0;System.out.println("增加用戶。。");return "cjj";}@Overridepublic void updateUser() {System.out.println("修改用戶。。");}@Overridepublic void deleteUser() {System.out.println("刪除用戶。。");}@Overridepublic void query() {System.out.println("查詢用戶。。");} } UserServiceImple.java package cn.tedu.aop;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.springframework.stereotype.Component; /*** FirstAspect:切面代碼*/ @Component public class FirstAspect {public void before(JoinPoint jp){ // 可以選擇額外的傳入一個JoinPoint連接點對象,必須用方法的第一個參數接收。Class clz = jp.getTarget().getClass();Signature signature = jp.getSignature(); // 通過JoinPoint對象獲取更多信息String name = signature.getName();System.out.println("1 -- before...["+clz+"]...["+name+"]...");}public Object around(ProceedingJoinPoint jp) throws Throwable{System.out.println("1 -- around before...");Object obj = jp.proceed(); //--顯式的調用目標方法System.out.println("1 -- around after...");return obj;}public void afterReturn(JoinPoint jp, Object msg){Class clz = jp.getTarget().getClass();Signature signature = jp.getSignature(); String name = signature.getName();System.out.println("1 -- afterReturn...["+clz+"]...["+name+"]...["+msg+"]...");}public void afterThrow(JoinPoint jp,Throwable e){Class clz = jp.getTarget().getClass();String name = jp.getSignature().getName();System.out.println("1 -- afterThrow..["+clz+"]..["+name+"].."+e.getMessage());}public void after(JoinPoint jp){Class clz = jp.getTarget().getClass();String name = jp.getSignature().getName();System.out.println("1 -- after..["+clz+"]..["+name+"]...");} } FirstAspect.java package cn.tedu.test;import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.tedu.service.UserService; /*** AOPTest:測試代碼*/ public class AOPTest {@Testpublic void test01(){ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = (UserService) context.getBean("userService");String result = userService.addUser("cjj"); // 一個連接點 System.out.println(result);} } AOPTes.java

五種通知的執行順序

1.在目標方法沒有拋出異常的情況下

前置通知

環繞通知的調用目標方法之前的代碼

目標方法

環繞通知的調用目標方法之后的代碼

后置通知

最終通知

2.在目標方法拋出異常的情況下

前置通知

環繞通知的調用目標方法之前的代碼

目標方法 拋出異常 異常通知

最終通知

3.如果存在多個切面

多切面執行時,采用了責任鏈設計模式。

切面的配置順序決定了切面的執行順序,多個切面執行的過程,類似于方法調用的過程,在環繞通知的proceed()執行時,去執行下一個切面或如果沒有下一個切面執行目標方法,從而達成了如下的執行過程:

?

如果目標方法拋出異常:

五種通知的常見使用場景

環繞通知

控制事務 權限控制

后置通知

記錄日志(方法已經成功調用)

異常通知

異常處理 控制事務

最終通知

記錄日志(方法已經調用,但不一定成功)

轉載于:https://www.cnblogs.com/chuijingjing/p/9806651.html

總結

以上是生活随笔為你收集整理的Spring AOP 五大通知类型的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。