Spring 事務管理中,傳播行為定義了業務方法之間調用時事務邊界的處理規則。在實際開發中,我們無法將所有業務邏輯寫在單一方法中,必須調用其他服務、DAO 或同事編寫的代碼。此時,理解並正確選擇事務傳播模式,是保證數據一致性的關鍵。
當事務方法 A 調用另一事務方法 B 時,B 方法應該在什麼事務上下文中執行?繼續 A 的事務?開啟新事務?還是嵌套在 A 事務中?這就是傳播行為要解決的問題。Spring 定義了 7 種傳播行為,其中最常用、最核心的三種是:
假設業務流程:methodA() 開啟事務,內部調用 methodB()。我們以 A 方法固定為 REQUIRED 為前提,分析 B 方法採用三種不同傳播行為的行為差異。
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
// 邏輯 A1
methodB(); // 加入 A 的事務
// 邏輯 A2
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
// 邏輯 B
}
行為: B 方法檢測到 A 已有事務,直接加入 A 的事務上下文。兩者共享同一事務,任一方拋出異常導致回滾,雙雙回滾。這是最常見的「業務整體原子性」場景。
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
// 邏輯 A1
methodB(); // 掛起 A 事務,B 獨立新事務
// 邏輯 A2
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 邏輯 B:獨立提交或回滾
}
行為: B 方法強制開啟新事務,A 的事務被掛起。B 事務獨立提交或回滾,不影響 A 事務。即使 B 回滾,A 仍可繼續提交。
典型應用: 日誌記錄、審計追蹤、發送通知等「非核心、不可阻塞主流程」的副作用操作。即使主業務失敗,日誌也必須落庫。
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
// 邏輯 A1
try {
methodB(); // 嵌套事務,基於保存點
} catch (Exception e) {
// 捕獲 B 的異常,A 可選擇繼續或回滾
}
// 邏輯 A2
}
@Transactional(propagation = Propagation.NESTED)
public void methodB() {
// 邏輯 B:可獨立回滾到保存點
}
行為: B 方法在 A 事務內部建立保存點。B 可獨立回滾到保存點,不影響 A 已執行的操作;但若 A 後續回滾,B 的操作也會連帶回滾(因屬於同一物理事務)。
關鍵限制: 僅 DataSourceTransactionManager(JDBC)支援,JtaTransactionManager 不支援。且需資料庫支援保存點。
| 維度 | REQUIRED | REQUIRES_NEW | NESTED |
|---|---|---|---|
| 事務關係 | 共享同一事務 | 完全獨立的兩個事務 | 嵌套事務(保存點) |
| B 回滾影響 A | 是(A 必須回滾) | 否(A 可獨立提交) | 否(B 僅回滾到保存點) |
| A 回滾影響 B | 是(B 已加入 A) | 否(B 已提交則不變) | 是(B 隸屬 A 物理事務) |
| 適用場景 | 業務整體原子性 | 獨立副作用(日誌、通知) | 部分操作可選回滾 |
| 事務管理器支援 | 所有 | JTA、JDBC | 僅 JDBC |
| 性能開銷 | 最低 | 較高(新連接、新事務) | 中等(保存點開銷) |
@Transactional 基於 AOP 代理,this.methodB() 繞過代理,傳播行為不生效。解決:注入自身 Bean 或提取到獨立 Servicetry-catch 捕獲異常未重拋,事務管理器感知不到異常。解決:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly() 或重拋異常RuntimeException 和 Error 觸發回滾。解決:@Transactional(rollbackFor = Exception.class)掌握這三大傳播模式的本質差異,結合具體業務語義選型,才能在複雜業務架構下構建健壯的事務邊界。建議在代碼審查階段重點檢查跨服務調用的傳播行為配置,避免「以為在事務中」實則「事務已失效」的隱患。