Spring?Boot?AOP與事務(wù)、異常處理交互的問題小結(jié)
Spring Boot AOP (四)與事務(wù)、異常處理交互
1. 引言
在企業(yè)項(xiàng)目中,AOP 不僅用于日志和性能監(jiān)控,還與 事務(wù)管理、異常處理 密切相關(guān)。理解 AOP、事務(wù)、異常三者的執(zhí)行順序 對(duì)架構(gòu)設(shè)計(jì)和問題排查至關(guān)重要。
Spring 事務(wù)是通過 AOP 代理實(shí)現(xiàn)的,@Transactional 注解會(huì)生成一個(gè)事務(wù)切面,織入目標(biāo)方法。
2. @Transactional 與 AOP 結(jié)合
2.1 核心機(jī)制
@Transactional注解會(huì)被TransactionInterceptor處理- Spring 使用 環(huán)繞通知(Around Advice)在方法調(diào)用前開啟事務(wù),方法執(zhí)行后提交或回滾事務(wù)
- 如果目標(biāo)方法拋出異常,事務(wù)回滾策略生效
2.2 示例代碼
@Service
public class UserService {
@Transactional
public void createUser(String name) {
System.out.println("創(chuàng)建用戶: " + name);
if (name.equals("error")) {
throw new RuntimeException("模擬異常");
}
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void logBefore(JoinPoint jp) {
System.out.println("日志前置: " + jp.getSignature());
}
@AfterReturning("execution(* com.example.service..*.*(..))")
public void logAfter(JoinPoint jp) {
System.out.println("日志后置: " + jp.getSignature());
}
}3. AOP 與事務(wù)執(zhí)行順序
| 切面 | 類型 | 執(zhí)行時(shí)機(jī) |
|---|---|---|
| LoggingAspect | @Before | 方法執(zhí)行前 |
| TransactionInterceptor | @Around | 方法執(zhí)行前開啟事務(wù) |
| 目標(biāo)方法 | - | 執(zhí)行業(yè)務(wù)邏輯 |
| TransactionInterceptor | @Around | 方法執(zhí)行后提交或回滾事務(wù) |
| LoggingAspect | @AfterReturning / @AfterThrowing | 方法返回后執(zhí)行日志/異常記錄 |
Mermaid 流程圖:AOP + 事務(wù) + 異常
flowchart TD
A[方法調(diào)用] --> B[LoggingAspect @Before]
B --> C[TransactionInterceptor @Around 前開啟事務(wù)]
C --> D[執(zhí)行目標(biāo)方法]
D -->|正常返回| E[TransactionInterceptor 提交事務(wù)]
D -->|異常拋出| F[TransactionInterceptor 回滾事務(wù)]
E --> G[LoggingAspect @AfterReturning]
F --> H[LoggingAspect @AfterThrowing]
G --> I[返回客戶端]
H --> I4. 異常通知與事務(wù)交互
4.1 異常通知觸發(fā)條件
- @AfterThrowing 僅在目標(biāo)方法拋出異常時(shí)執(zhí)行
- @AfterReturning 僅在方法正常返回時(shí)執(zhí)行
- @After 無論成功或異常都會(huì)執(zhí)行
4.2 示例
@Aspect
@Component
public class ExceptionAspect {
@AfterThrowing(pointcut = "execution(* com.example.service..*.*(..))", throwing = "ex")
public void logException(JoinPoint jp, Throwable ex) {
System.out.println("捕獲異常: " + ex.getMessage() + " 方法: " + jp.getSignature());
}
}5. 方法調(diào)用順序示意圖

6. 多切面 + 異常 + 事務(wù)組合
@Aspect
@Component
@Order(1)
public class LoggingAspect {
@Before("execution(* com.example.service..*.*(..))")
public void before(JoinPoint jp) { System.out.println("日志前置"); }
}
@Aspect
@Component
@Order(2)
public class TransactionAspect {
@Around("execution(* com.example.service..*.*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("事務(wù)開始");
try {
Object result = pjp.proceed();
System.out.println("事務(wù)提交");
return result;
} catch (Throwable ex) {
System.out.println("事務(wù)回滾");
throw ex;
}
}
}
@Aspect
@Component
@Order(3)
public class MetricsAspect {
@AfterReturning("execution(* com.example.service..*.*(..))")
public void afterReturning(JoinPoint jp) { System.out.println("性能監(jiān)控"); }
}執(zhí)行順序示意
flowchart TD
A[方法調(diào)用] --> B[LoggingAspect @Before]
B --> C[TransactionAspect @Around 前]
C --> D[目標(biāo)方法執(zhí)行]
D -->|正常| E[TransactionAspect 提交事務(wù)]
D -->|異常| F[TransactionAspect 回滾事務(wù)]
E --> G[MetricsAspect @AfterReturning]
F --> H[異常處理切面執(zhí)行]
G --> I[返回客戶端]
H --> I7. 小結(jié)
- Spring 事務(wù)基于 AOP 環(huán)繞通知實(shí)現(xiàn)
- 異常通知和事務(wù)回滾緊密關(guān)聯(lián)
- 多切面情況下,通知順序由
@Order或Ordered控制 - Mermaid 圖直觀展示了 多切面 + 事務(wù) + 異常 的方法調(diào)用鏈
- 理解這個(gè)順序有助于正確設(shè)計(jì)日志、事務(wù)、異常切面,避免回滾異常被切面吞掉或日志記錄錯(cuò)位
到此這篇關(guān)于Spring Boot AOP與事務(wù)、異常處理交互的問題小結(jié)的文章就介紹到這了,更多相關(guān)Spring Boot AOP事務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot實(shí)現(xiàn)STOMP協(xié)議的WebSocket的方法步驟
這篇文章主要介紹了Spring Boot實(shí)現(xiàn)STOMP協(xié)議的WebSocket的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05
synchronized底層原理之JVM層面的鎖實(shí)現(xiàn)細(xì)節(jié)與流程
本文從JVM底層視角,詳細(xì)拆解了synchronized的實(shí)現(xiàn)邏輯,涵蓋鎖的存儲(chǔ)載體(對(duì)象頭的MarkWord)、鎖的觸發(fā)指令(monitorenter/monitorexit指令和ACC_SYNCHRONIZED標(biāo)志位)以及鎖的調(diào)度機(jī)制,感興趣的朋友跟隨小編一起看看吧2026-01-01
java 各個(gè)JSONObject的區(qū)別小結(jié)
在Java中,??JSONObject???是用于表示JSON對(duì)象的類,但不同庫(kù)提供的JSONObject???實(shí)現(xiàn)之間存在一些差異,本文幾個(gè)常見的JSON庫(kù)及其JSONObje,感興趣的可以了解一下2025-10-10
Java實(shí)現(xiàn)分庫(kù)分表實(shí)踐指南
在開發(fā)中我們經(jīng)常使用到分庫(kù)分表,但是一般是我們前期就已經(jīng)做了規(guī)劃,對(duì)數(shù)據(jù)庫(kù)怎么劃分,對(duì)哪些表進(jìn)行分表,這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)分庫(kù)分表的相關(guān)資料,需要的朋友可以參考下2024-01-01
Java 內(nèi)置接口 Serializable示例詳解
這篇文章主要為大家介紹了Java 內(nèi)置接口 Serializable示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
springboot3.2整合mybatis-plus詳細(xì)代碼示例
這篇文章主要給大家介紹了關(guān)于springboot3.2整合mybatis-plus的相關(guān)資料,Spring Boot是一個(gè)非常流行的Java Web框架,可以快速地搭建Web應(yīng)用程序,需要的朋友可以參考下2023-12-12
使用PageHelper插件實(shí)現(xiàn)Service層分頁(yè)
這篇文章主要為大家詳細(xì)介紹了使用PageHelper插件實(shí)現(xiàn)Service層分頁(yè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04

