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

Spring 事務管理深度解析:聲明式事務與傳播行為實戰

     編輯:Java 相關知識

Spring Framework 作為輕量級 J2EE 應用框架,其核心優勢在於 IoC 容器與強大的事務管理能力。Spring 的聲明式事務可應用於任意 POJO,功能對標 EJB 容器管理事務 (CMT),並支援從簡單 JDBC 事務到完整 JTA 分散式事務的多種後端策略。本文詳細探討 Spring 事務管理機制,重點講解基於 JTA 的聲明式事務配置、事務傳播行為、與 J2EE 伺服器事務協調器的無縫整合,展示其作為傳統 EJB CMT 替代方案的可行性。

一、 POJO 聲明式事務配置範例

以 Spring 經典 PetClinic 應用的核心服務 Clinic 為例,展示標準 XML Bean 定義:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName"><value>java:comp/env/jdbc/petclinic</value></property>
</bean>

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"/>

<bean id="clinicTarget" class="org.springframework.samples.petclinic.jdbc.JdbcClinic">
    <property name="dataSource"><ref bean="dataSource"/></property>
</bean>

<bean id="clinic" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="target"><ref bean="clinicTarget"/></property>
    <property name="transactionAttributes">
        <props>
            <prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
            <prop key="store*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

配置核心要素解析

  1. DataSource:JNDI 查找應用伺服器管理的資料源。
  2. PlatformTransactionManager:此處使用 JtaTransactionManager,委託 J2EE 伺服器事務協調器。
  3. 目標服務實現:純 POJO (JdbcClinic),封裝業務與資料存取邏輯,無需感知 Spring。
  4. 事務代理:TransactionProxyFactoryBean 為目標服務織入事務行為,根據方法名模式匹配事務屬性。

補充: Spring 亦支援 Commons Attributes 或 JDK 5.0 Annotation 實現自動代理與原始碼級元資料配置,本文不贅述。

二、 服務介面與實現:純 POJO 設計

public interface Clinic {
    Pet loadPet(int id);
    void storePet(Pet pet);
    // ...
}

public class JdbcClinic implements Clinic {
    private DataSource dataSource;
    public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; }

    public Pet loadPet(int id) {
        try (Connection con = dataSource.getConnection()) { /* JDBC 操作 */ }
        catch (SQLException ex) { /* 異常處理 */ }
    }

    public void storePet(Pet pet) {
        try (Connection con = dataSource.getConnection()) { /* JDBC 操作 */ }
        catch (SQLException ex) { /* 異常處理 */ }
    }
}

代碼簡潔純粹,事務管理由代理層完全接管。實際專案中建議搭配 Spring JDBC 模板類 (JdbcTemplate) 簡化資源管理。

三、 事務代理機制與 AOP 本質

客戶端獲取 clinic Bean 實為事務代理,調用方法時隱式觸發「事務攔截器」:

  1. 檢查事務屬性,決定是否開啟新事務或加入現有事務。
  2. 委託目標方法執行業務邏輯。
  3. 方法返回時提交事務,拋出異常則回滾 (預設僅 RuntimeException/Error 觸發回滾)。

AOP 代理結構圖

圖 1:具備「Advisor 鏈」與目標對象的 AOP 代理結構

客戶端調用範例

WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(servletContext);
Clinic clinic = (Clinic) ctx.getBean("clinic");
Pet pet = new Pet(); pet.setName("my new cat");
clinic.storePet(pet); // 隱式開啟事務,方法結束提交/回滾

四、 事務傳播行為詳解

事務屬性中最關鍵的是傳播行為,定義方法調用時事務邊界處理方式:

傳播常量行為描述對應 EJB CMT
PROPAGATION_REQUIRED支援當前事務,不存在則新建 (最常用)Required
PROPAGATION_SUPPORTS支援當前事務,不存在則非事務執行Supports
PROPAGATION_MANDATORY必須在事務中執行,否則拋出異常Mandatory
PROPAGATION_REQUIRES_NEW新建事務,掛起當前事務RequiresNew
PROPAGATION_NOT_SUPPORTED非事務執行,掛起當前事務NotSupported
PROPAGATION_NEVER非事務執行,存在事務則拋出異常Never
PROPAGATION_NESTED巢狀事務 (需 JDBC 3.0 Savepoint 或 JTA 支援)Spring 專屬擴展

前六種策略與 EJB CMT 常量名一致,EJB 開發者極易上手。PROPAGATION_NESTED 是 Spring 獨有擴展,需底層事務管理器支援保存點機制。

其他事務屬性

  • readOnly:標記唯讀事務,提示底層優化 (如 Hibernate 避免 dirty checking)。
  • timeout:事務超時秒數,JTA 環境下傳遞給伺服器協調器。
  • rollback rules:自定義回滾規則,如 -PetClinicException 表示拋出該檢查型異常時回滾。
<prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop>

五、 PlatformTransactionManager 策略選擇

Spring 事務抽象核心為 PlatformTransactionManager 介面,提供多種實現:

類別實現類適用場景
本地事務DataSourceTransactionManager單一資料庫 (JDBC)
本地事務HibernateTransactionManager單一資料庫 (Hibernate)
全域事務JtaTransactionManager跨多資源 (J2EE 伺服器 JTA)

核心價值:應用代碼與聲明式事務解耦,僅需切換 TransactionManager 實現即可適應不同部署環境 (如 Tomcat + 單庫 → WebLogic + 多庫),無需修改業務代碼。

六、 JTA 事務掛起關鍵:TransactionManager vs UserTransaction

標準 JtaTransactionManager 預設從 java:comp/UserTransaction 獲取 UserTransaction,**不支援事務掛起** (即 PROPAGATION_REQUIRES_NEW、PROPAGATION_NOT_SUPPORTED 失效),因 UserTransaction 缺乏 suspend/resume 方法。

解決方案:注入 JTA TransactionManager 實例 (提供標準掛起/恢復 API)。但 J2EE 未規範其 JNDI 名稱,需廠商特定配置:

<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManagerName"><value>vendorSpecificJndiLocation</value></property>
</bean>

WebLogic 整合最佳實踐

  • WebLogic 官方 JNDI 名稱:javax.transaction.TransactionManager。
  • Spring 提供專用 WebLogicJtaTransactionManager 適配器,額外支援:
    1. 事務命名:Spring 事務名暴露給 WebLogic 監控主控台。
    2. 每事務隔離級別:突破標準 JTA 限制,實現事務級隔離級別控制。
    3. 強制事務恢復:即使事務標記為回滾,仍可強制恢復 (forceResume())。

WebLogic 事務監控主控台

圖 2:WebLogic Server 事務監控主控台

七、 Spring 與 EJB CMT 關係定位

  • 替代關係:POJO 聲明式事務可完全替代傳統 EJB CMT,特別適合輕量級架構。
  • 協作關係:Spring 容器可作為 EJB Facade 後端管理 DAO/細粒度業務對象。EJB 驅動事務時,Spring 自動檢測並參與現有事務 (如 Hibernate 隱式資源管理)。
  • 優勢:DAO 實現與運行環境解耦,便於單元測試 (脫離容器) 與跨環境重用。

八、 結論

Spring 提供了全方位、非侵入式的事務管理解決方案:

  • POJO 聲明式事務簡化開發,支援靈活傳播行為與回滾規則。
  • 統一 PlatformTransactionManager 抽象屏蔽底層差異,實現策略熱插拔。
  • 深度整合 WebLogic JTA 擴展,釋放商業伺服器高階事務能力。
  • 作為 EJB CMT 的有力替代者,賦予輕量級架構企業級事務能力,極大提升可測試性與重用性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved