Spring 對 Hibernate 事務的管理核心由三部分組成:DataSource(數據源)、TransactionManager(事務管理器)、代理機制(AOP 代理)。無論採用哪種配置方式,前兩者基本固定,差異在於如何定義事務代理。本文梳理 Spring 早期版本(2.x/3.x)中五種經典的聲明式事務配置模式,幫助理解事務管理演進脈絡。
所有示例共用以下基礎 Bean 定義(DataSource、SessionFactory、HibernateTransactionManager),此處省略重複 XML,僅展示代理配置差異。
最原始方式,為每個目標 Bean 定義一個 TransactionProxyFactoryBean,屬性包括 transactionManager、target、proxyInterfaces、transactionAttributes。
<bean id="userDaoTarget" class="com.dao.impl.UserDaoImpl">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="userDaoTarget"/>
<property name="proxyInterfaces" value="com.dao.UserDao"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
缺點:Bean 多時配置極其冗餘,維護成本高。
定義一個抽象的父 Bean(abstract="true"、lazy-init="true"),子 Bean 通過 parent="base" 繼承事務屬性,僅需指定 target。
<bean id="baseTxProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true" lazy-init="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props><prop key="*">PROPAGATION_REQUIRED</prop></props>
</property>
</bean>
<bean id="userDao" parent="baseTxProxy">
<property name="target" ref="userDaoTarget"/>
</bean>
優點:減少重複配置;缺點:本質仍是逐個 Bean 代理。
使用 BeanNameAutoProxyCreator 根據 Bean 名稱模式(如 *DaoImpl)自動創建代理,攔截器引用獨立定義的 TransactionInterceptor。
<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props><prop key="*">PROPAGATION_REQUIRED</prop></props>
</property>
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames"><list><value>*DaoImpl</value></list></property>
<property name="interceptorNames"><list><value>transactionInterceptor</value></list></property>
</bean>
優點:零侵入業務 Bean 定義,批量代理;缺點:命名模式匹配不夠靈活。
引入 tx 和 aop Schema,通過 <tx:advice> 定義事務屬性,<aop:config> 綁定切點表達式,實現聲明式事務的標準化配置。
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoMethods" expression="execution(* com.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoMethods"/>
</aop:config>
優點:關注點分離,切點表達式強大,配置清晰,成為 XML 時代主流。
啟用 <tx:annotation-driven/>,在類或方法上標註 @Transactional,Spring 自動識別並織入事務邏輯。
<context:component-scan base-package="com.dao"/> <tx:annotation-driven transaction-manager="transactionManager"/>
業務代碼:
@Repository
@Transactional
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
@Transactional(readOnly = true)
public void getUser() { /* ... */ }
}
優點:零 XML 事務配置,細粒度控制,代碼即文檔,是當前 Spring Boot 等現代框架的默認選擇。
| 方式 | 適用場景 | 推薦指數 |
|---|---|---|
| 獨立代理 | 極少數 Bean、舊項目維護 | ★ |
| 父 Bean 繼承 | 中小項目、XML 必須 | ★★ |
| 自動代理器 | 命名規範統一、批量代理 | ★★★ |
| TX/AOP XML | 傳統 Spring MVC、需集中管理事務策略 | ★★★★ |
| @Transactional | 現代 Spring/Spring Boot 項目、首選方案 | ★★★★★ |
理解這五種方式的演進,不僅有助於維護老項目,更能深刻體會 Spring 從「配置驅動」到「約定優於配置」再到「註解驅動」的設計哲學變遷。