Spring 事務管理是企業級開發核心技能。本文系統整理聲明式事務的四種歷史配置演進(tx 標籤、代理工廠、攔截器、註解驅動)與編程式註解方式,對比優劣適用場景,提供生產環境選型指南。
無論何種方式,Spring 事務配置必包含:
DataSourceTransactionManager、HibernateTransactionManager、JtaTransactionManager)<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="del*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoMethods" expression="execution(* com.dao.*.*(..))"/>
<aop:advisor pointcut-ref="daoMethods" advice-ref="txAdvice"/>
</aop:config>
優點:業務代碼零侵入、切點表達式靈活、事務屬性集中管理
缺點:XML 配置較繁瑣、需理解 AOP 概念
<bean id="txProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="add*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="modify*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="del*">PROPAGATION_REQUIRED,-Exception</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="userDao" parent="txProxy">
<property name="target">
<bean class="com.dao.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</property>
</bean>
優點:Spring 1.x/2.x 經典寫法、abstract="true" + parent 復用配置
缺點:每個 Bean 需單獨代理、配置膨脹、已被 tx:advice 取代
<bean id="txInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager"/> <property name="transactionAttributes">...</property> </bean> <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"><list><value>txInterceptor</value></list></property> <property name="beanNames"><list><value>*Dao</value></list></property> </bean>
缺點:配置複雜、靠 Bean 名稱匹配脆弱、不推薦新專案使用
<!-- 啟用註解掃描 --> <context:annotation-config/> <tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional // 類級:默認事務屬性
public class UserDaoImpl {
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void addUser(User user) { ... }
@Transactional(readOnly = true)
public User findUser(String id) { ... }
}
優點:代碼與配置合一、IDE 支援重構、細粒度控制、Spring Boot 時代標配
缺點:大型專案註解分散、需掃描啟動、僅適用於 public 方法(代理機制限制)
| 傳播類型 | 行為 | 適用場景 |
|---|---|---|
| REQUIRED | 支援當前事務,無則新建 | 90% 業務方法默認選擇 |
| SUPPORTS | 支援當前事務,無則非事務執行 | 查詢方法、只讀操作 |
| MANDATORY | 必須在事務中執行,無則拋異常 | 強制要求事務上下文的核心操作 |
| REQUIRES_NEW | 新建事務,掛起當前事務 | 獨立提交:日誌記錄、審計、發送通知 |
| NOT_SUPPORTED | 非事務執行,掛起當前事務 | 長時間計算、外部 API 調用 |
| NEVER | 非事務執行,有事務則拋異常 | 嚴格禁止事務的場景 |
| NESTED | 嵌套事務(保存點),外層回滾內層跟隨 | 批次處理部分回滾、JDBC 3.0+ 支援 |
@Autowired
private TransactionTemplate txTemplate;
public void complexBusinessLogic() {
txTemplate.execute(status -> {
try {
dao.step1();
dao.step2();
return "success";
} catch (Exception e) {
status.setRollbackOnly();
throw new BusinessException("業務失敗", e);
}
});
}
適用場景:事務邊界動態決定、需在事務中穿插非事務邏輯、極少數註解無法覆蓋的複雜場景。
| 專案類型 | 推薦方式 | 理由 |
|---|---|---|
| Spring Boot 微服務 | @Transactional + 註解驅動 | 零配置、標準化、生態整合最佳 |
| 傳統 Spring XML 專案 | tx:advice + aop:config | 業務代碼純淨、集中管理、團隊協作友好 |
| 大型單體遷移中 | 混合:核心模塊註解、邊緣模塊 XML | 漸進式遷移、風險可控 |
| 需動態事務控制 | TransactionTemplate | 程式化控制事務邊界 |
rollbackFor = Exception.classSpring 事務管理從 XML 代理演進到註解驅動,本質是 AOP 環繞通知 + ThreadLocal 綁定連接。理解四種配置的歷史脈絡與底層原理,能在遷移升級、疑難排查、架構決策中遊刃有餘。現代開發:首選 @Transactional,輔以 tx:advice 處理跨模塊統一策略。