Spring 聲明式事務無論採用哪種代理機制,核心始終包含三個 Bean:
DataSourceTransactionManager、HibernateTransactionManager、JtaTransactionManager)適用:早期 Spring 1.x/2.x,少量 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.bluesky.spring.dao.GeneratorDao"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
缺點:配置冗長,每個目標 Bean 需額外定義一個代理 Bean。
優化:提取公共事務屬性到父 Bean,子 Bean 繼承
<bean id="transactionBase" 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="transactionBase">
<property name="target" ref="userDaoTarget"/>
</bean>
核心:定義 TransactionInterceptor,配合 BeanNameAutoProxyCreator 批量代理
<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>*Dao</value></list></property>
<property name="interceptorNames"><list><value>transactionInterceptor</value></list></property>
</bean>
優勢:零侵入業務 Bean,通過命名規則(如 *Dao)批量應用事務。
特點:聲明式切點表達式,關注點分離更徹底
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="daoPointcut" expression="execution(* com.bluesky.spring.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="daoPointcut"/>
</aop:config>
配置極簡:僅需啟用注解驅動
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.bluesky"/>
業務代碼:在類或方法上標註 @Transactional
@Repository
@Transactional // 類級別:所有 public 方法開啟事務
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
public List<User> listUsers() {
return getSession().createQuery("from User").list();
}
}
| 維度 | 方式一 | 方式二 | 方式三 | 方式四 | 方式五 |
|---|---|---|---|---|---|
| 配置複雜度 | 高 | 中 | 中 | 低 | 極低 |
| 維護性 | 差 | 一般 | 好 | 優 | 最佳 |
| 靈活性(方法級控制) | 高 | 高 | 中 | 高 | 最高 |
| 推薦場景 | 歷史項目維護 | 早期項目遷移 | 批量同類 Bean | 新項目 XML 風格 | 現代 Spring 項目 |
REQUIRED(默認,支持當前事務)、REQUIRES_NEW(掛起當前、新建)、NESTED(嵌套保存點)READ_COMMITTED(默認)、REPEATABLE_READ、SERIALIZABLEreadOnly=true 針對查詢方法,提示數據庫/持久層優化RuntimeException/Error 觸發回滾,rollbackFor=Exception.class 可擴展timeout=30 秒,防止長事務佔用資源從繁瑣的 TransactionProxyFactoryBean 到優雅的 @Transactional,Spring 事務配置經歷了「配置外部化 → 切點表達式 → 註解驅動」的演進。新項目首選方式五(全注解),配合 @Transactional(readOnly=true) 細粒度控制,代碼意圖清晰、維護成本最低。僅在需動態切換事務策略、非 Spring 容器管理 Bean 等特殊場景考慮方式三/四。