一文搞懂Spring AOP的五大通知類型
一、通知類型
Advice
直譯為通知,也有人翻譯為 “增強處理”,共有 5 種類型,如下表所示。
通知類型 | 注解 | 說明 |
---|---|---|
before(前置通知) | @Before | 通知方法在目標方法調(diào)用之前執(zhí)行 |
after(后置通知) | @After | 通知方法在目標方法返回或異常后調(diào)用 |
after-returning(返回通知) | @AfterReturning | 通知方法會在目標方法返回后調(diào)用 |
after-throwing(異常通知) | @AfterThrowing | 通知方法會在目標方法拋出異常后調(diào)用 |
around(環(huán)繞通知) | @Around | 通知方法會將目標方法封裝起來 |
二、環(huán)境準備
添加AOP依賴
在pom.xml
文件里添加Spring AOP和AspectJ的jar包依賴
<dependencies> <!--包含Spring AOP:有基本的AOP功能--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> <!--AspectJ框架有更強大的AOP功能--> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency> </dependencies>
創(chuàng)建目標接口和實現(xiàn)類
/*UserDao接口*/ public interface UserDao { public void save(); public int update(); } /*UserDaoImpl實現(xiàn)類*/ @Repository public class UserDaoImpl implements UserDao { @Override public void save() { System.out.println("正在執(zhí)行 UserDao 的 save 方法"); } @Override public int update() { System.out.println("正在執(zhí)行 UserDao 的 update 方法"); return 1; } }
創(chuàng)建通知類
創(chuàng)建通知類,并指定切入點
/*通知類*/ @Component//將這個類定義成 Bean @Aspect//將這個Bean定義為切面 public class MyAdvice { //指定UserDao類中的save方法為切入點 @Pointcut("execution(void com.bighorn.dao.UserDao.save())") private void pt1(){} //指定UserDao類中的update方法為切入點 @Pointcut("execution(int com.bighorn.dao.UserDao.update())") private void pt2(){} }
創(chuàng)建Spring核心配置類
/*Spring核心配置類*/ @Configuration @ComponentScan("com.bighorn") //開啟注解掃描 @EnableAspectJAutoProxy //開啟 AspectJ 的自動代理 public class SpringConfig { }
編寫運行程序
public class App { public static void main(String[] args) throws SQLException { //獲取配置類初始化容器 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //從容器中獲取UserDao對象 UserDao userDao = context.getBean(UserDao.class); //調(diào)用userDao的方法 userDao.save(); } }
三、添加通知
普通通知
在MyAdvice
這個通知類中添加前置通知、后置通知、返回后通知、異常后通知及相關注解。
//前置通知 @Before("pt1()") public void before() { System.out.println("before advice ..."); } //后置通知 @After("pt1()") public void after() { System.out.println("after advice ..."); } //返回后通知 @AfterReturning("pt1()") public void afterReturning() { System.out.println("afterReturning advice ..."); } //異常后通知 @AfterThrowing("pt1()") public void afterThrowing() { System.out.println("afterThrowing advice ..."); }
觀察運行App程序后的截圖,發(fā)現(xiàn)并沒有顯示異常后通知
手動在save()
方法中添加一行代碼:int i = 1/0
,造成異常后再次運行App。
發(fā)現(xiàn)異常后通知有了,但是運行后通知卻消失了。
綜上所述: 前置通知和后置通知是一定會執(zhí)行的,而返回后通知是需要在原始方法正常執(zhí)行后才會被執(zhí)行,異常后通知是需要原始方法拋出異常才會被執(zhí)行
環(huán)繞通知(重點)
環(huán)繞通知是非常強大的通知,能夠完成上述四種通知的所有功能。
/** * 環(huán)繞通知需要攜帶ProceedingJoinPoint類型的參數(shù) * 環(huán)繞通知類似于動態(tài)代理的全過程:ProceedingJoinPoint類型的參數(shù)可以決定是否執(zhí)行目標方法 * 環(huán)繞通知必須要有返回值,返回值即為目標方法的返回值 * @param pjp * @return Object */ @Around("pt2()") public Object around(ProceedingJoinPoint pjp) { Object result = null; try { System.out.println("這是環(huán)繞通知中的前置通知......"); //執(zhí)行目標方法 result = pjp.proceed(); System.out.println("這是環(huán)繞通知中的返回通知......"); } catch (Throwable e) { System.out.println("這是環(huán)繞通知中的異常通知......"); } System.out.println("這是環(huán)繞通知中的后置通知......"); return result; }
修改App類,調(diào)用UserDao的update()
方法,運行程序,觀察結(jié)果。
public class App { public static void main(String[] args) throws SQLException { //獲取配置類初始化容器 ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); //從容器中獲取UserDao對象 UserDao userDao = context.getBean(UserDao.class); //調(diào)用userDao的update方法 userDao.update(); } }
運行結(jié)果如下
注意點
使用環(huán)繞通知必須傳入形參ProceedingJoinPoint
,并使用pjp.proceed()方法
實現(xiàn)對原始方法的調(diào)用,進而實現(xiàn)原始方法調(diào)用前后同時添加通知
通知中如果未使用使用pjp.proceed()方法
實現(xiàn)對原始方法的調(diào)用,則將跳過原始方法的執(zhí)行
原始方法的返回值類型決定環(huán)繞通知的返回值類型。原始方法若不接收返回值,通知方法的返回值類型可以設置成void,也可以設置成Object;如果接收返回值,最好設定為Object類型。
由于無法預知原始方法運行后是否會拋出異常,因此環(huán)繞通知方法必須要處理Throwable異常
以上就是一文搞懂Spring AOP的五大通知類型的詳細內(nèi)容,更多關于Spring AOP通知類型的資料請關注腳本之家其它相關文章!
相關文章
PowerJob的QueryConvertUtils工作流程源碼解讀
這篇文章主要為大家介紹了PowerJob的QueryConvertUtils工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2024-01-01Springboot自定義mybatis攔截器實現(xiàn)擴展
本文主要介紹了Springboot自定義mybatis攔截器實現(xiàn)擴展,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12詳解使用spring cloud config來統(tǒng)一管理配置文件
這篇文章主要介紹了詳解使用spring cloud config來統(tǒng)一管理配置文件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-12-12