首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Spring 事務配置五大方式全解析:從 XML 到全註解演進

     編輯:Java 相關知識

前言

Spring 事務管理的核心三要素——DataSource、TransactionManager、代理機制——前兩者隨數據訪問技術變化,後者決定事務攔截粒度與配置風格。本文梳理 Spring 2.5 時代五種主流配置方式,展示從繁瑣 XML 向聲明式註解演進的脈絡。

核心基礎設施(所有方式共用)

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

註:若用 JPA/JDBC,分別換成 EntityManagerFactory/DataSource 及對應 TransactionManager 實現。

方式一:每個 Bean 獨立代理

特點:每個目標 Bean 需顯式包裝 TransactionProxyFactoryBean,屬性重複度高。

<bean id="userDaoTarget" class="com.bluesky.spring.dao.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.bluesky.spring.dao.GeneratorDao"/>
    <property name="transactionAttributes">
        <props><prop key="*">PROPAGATION_REQUIRED</prop></props>
    </property>
</bean>

缺點:DAO 增加時需複製大量 XML,維護成本高。

方式二:共享父 Bean 定義

特點:抽象父 Bean transactionBase 定義公共事務屬性,子 Bean 通過 parent="transactionBase" 繼承,僅需指定 target。

<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
      lazy-init="true" abstract="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>

優勢:減少重複配置,但本質仍是逐個 Bean 代理。

方式三:自動代理 + 事務攔截器

特點:使用 BeanNameAutoProxyCreator 按 Bean 名稱模式(如 *Dao)批量創建代理,攔截器 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>*Dao</value></list></property>
    <property name="interceptorNames"><list><value>transactionInterceptor</value></list></property>
</bean>
<bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">...</bean>

優勢:零侵入業務 Bean 定義,新增 DAO 自動生效。

方式四:<tx:advice> + <aop:config>(Schema 風格)

特點:Spring 2.0+ 引入 tx/aop 命名空間,用切點表達式精準匹配攔截點,配置可讀性大增。

<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>

優勢:聲明式 AOP 風格,切點表達式靈活控制攔截範圍,成為 XML 時代主流。

方式五:全註解驅動

特點:<tx:annotation-driven/> 啟用 @Transactional 掃描,業務類直接加註解,零 XML 代理配置。

<context:component-scan base-package="com.bluesky"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional
@Component("userDao")
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    public List<User> listUsers() {
        return getSession().createQuery("from User").list();
    }
}

優勢:配置最簡潔,註解與代碼共存,易維護,現代 Spring 應用標配。

五種方式對比總結

方式配置量靈活度適用場景
1. 獨立代理極大單 Bean 級精細極少量 Bean、需極致差異化
2. 父 Bean 繼承大單 Bean 級中小項目、XML 時代過渡方案
3. 自動代理 + 攔截器中按名稱模式批量命名規範統一的傳統項目
4. tx:aop Schema中小切點表達式任意匹配XML 配置主流項目、需精細控制
5. 全註解極小類/方法級註解控制現代 Spring/Spring Boot 項目首選

最佳實踐建議

  1. 新項目首選方式五:@Transactional + @Service/@Repository,配合 Spring Boot 自動配置,零 XML。
  2. 舊項目遷移路徑:1/2 → 3 → 4 → 5,逐步降低 XML 依賴。
  3. 事務屬性細化:不要只用 PROPAGATION_REQUIRED,根據業務設置 readOnly、isolation、timeout、rollbackFor。
  4. 避免自我調用失效:同類內部方法調用繞過代理,需注入自身或拆分類。

事務配置的演進史,本質上是 Spring 從「配置驅動」向「約定優於配置」、「註解驅動」演進的縮影。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved