spring 事務管理 四

Spring 的聲明式事務管理概述

  Spring 的聲明式事務管理在底層是建立在 AOP 的基礎之上的。其本質是對方法前後進行攔截,然後在目標方法開始之前創建或者加入一個事務,在執行完目標方法之後根據執行情況提交或者回滾事務。

  聲明式事務最大的優點就是不需要通過編程的方式管理事務,這樣就不需要在業務邏輯代碼中摻雜事務管理的代碼,只需在配置文件中做相關的事務規則聲明(或通過等價的基於標註的方式),便可以將事務規則應用到業務邏輯中。因爲事務管理本身就是一個典型的橫切邏輯,正是 AOP 的用武之地。Spring 開發團隊也意識到了這一點,爲聲明式事務提供了簡單而強大的支持。

  聲明式事務管理曾經是 EJB 引以爲傲的一個亮點,如今 Spring 讓 POJO 在事務管理方面也擁有了和 EJB 一樣的待遇,讓開發人員在 EJB 容器之外也用上了強大的聲明式事務管理功能,這主要得益於 Spring 依賴注入容器和 Spring AOP 的支持。依賴注入容器爲聲明式事務管理提供了基礎設施,使得 Bean 對於 Spring 框架而言是可管理的;而 Spring AOP 則是聲明式事務管理的直接實現者,這一點通過清單8可以看出來。
 和編程式事務相比,聲明式事務唯一不足地方是,後者的最細粒度只能作用到方法級別,無法做到像編程式事務那樣可以作用到代碼塊級別。但是即便有這樣的需求,也存在很多變通的方法,比如,可以將需要進行事務管理的代碼塊獨立爲方法等等。

  下面就來看看 Spring 爲我們提供的聲明式事務管理功能。

  基於 TransactionInter... 的聲明式事務管理

  最初,Spring 提供了 TransactionInterceptor 類來實施聲明式事務管理功能。先看清單8的配置文件:

  清單 8. 基於 TransactionInterceptor 的事務管理示例配置文件

<beans...>
......
<bean id="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="bankServiceTarget"
class="footmark.spring.core.tx.declare.origin.BankServiceImpl">
<property name="bankDao" ref="bankDao"/>
</bean>
<bean id="bankService"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="bankServiceTarget"/>
<property name="interceptorNames">
<list>
<idref bean="transactionInterceptor"/>
</list>
</property>
</bean>
......
</beans>

 首先,我們配置了一個 TransactionInterceptor 來定義相關的事務規則,他有兩個主要的屬性:一個是 transactionManager,用來指定一個事務管理器,並將具體事務相關的操作委託給它;另一個是 Properties 類型的 transactionAttributes 屬性,它主要用來定義事務規則,該屬性的每一個鍵值對中,鍵指定的是方法名,方法名可以使用通配符,而值就表示相應方法的所應用的事務屬性。

  指定事務屬性的取值有較複雜的規則,這在 Spring 中算得上是一件讓人頭疼的事。具體的書寫規則如下:

傳播行爲 [,隔離級別] [,只讀屬性] [,超時屬性] [不影響提交的異常] [,導致回滾的異常]

  傳播行爲是唯一必須設置的屬性,其他都可以忽略,Spring爲我們提供了合理的默認值。

  傳播行爲的取值必須以“PROPAGATION_”開頭,具體包括:PROPAGATION_MANDATORY、PROPAGATION_NESTED、PROPAGATION_NEVER、PROPAGATION_NOT_SUPPORTED、PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_SUPPORTS,共七種取值。

  隔離級別的取值必須以“ISOLATION_”開頭,具體包括:ISOLATION_DEFAULT、ISOLATION_READ_COMMITTED、ISOLATION_READ_UNCOMMITTED、ISOLATION_REPEATABLE_READ、ISOLATION_SERIALIZABLE,共五種取值。

  如果事務是隻讀的,那麼我們可以指定只讀屬性,使用“readOnly”指定。否則我們不需要設置該屬性。

  超時屬性的取值必須以“TIMEOUT_”開頭,後面跟一個int類型的值,表示超時時間,單位是秒。

  不影響提交的異常是指,即使事務中拋出了這些類型的異常,事務任然正常提交。必須在每一個異常的名字前面加上“+”。異常的名字可以是類名的一部分。比如“+RuntimeException”、“+tion”等等。
導致回滾的異常是指,當事務中拋出這些類型的異常時,事務將回滾。必須在每一個異常的名字前面加上“-”。異常的名字可以是類名的全部或者部分,比如“-RuntimeException”、“-tion”等等。

  以下是兩個示例:

<property name="*Service">
PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,TIMEOUT_20,
+AbcException,+DefException,-HijException
</property>

  以上表達式表示,針對所有方法名以 Service 結尾的方法,使用 PROPAGATION_REQUIRED 事務傳播行爲,事務的隔離級別是 ISOLATION_READ_COMMITTED,超時時間爲20秒,當事務拋出 AbcException 或者 DefException 類型的異常,則仍然提交,當拋出 HijException 類型的異常時必須回滾事務。這裏沒有指定"readOnly",表示事務不是隻讀的。

<property name="test">PROPAGATION_REQUIRED,readOnly</property>

  以上表達式表示,針對所有方法名爲 test 的方法,使用 PROPAGATION_REQUIRED 事務傳播行爲,並且該事務是隻讀的。除此之外,其他的屬性均使用默認值。比如,隔離級別和超時時間使用底層事務性資源的默認值,並且當發生未檢查異常,則回滾事務,發生已檢查異常則仍提交事務。

  配置好了 TransactionInterceptor,我們還需要配置一個 ProxyFactoryBean 來組裝 target 和advice。這也是典型的 Spring AOP 的做法。通過 ProxyFactoryBean 生成的代理類就是織入了事務管理邏輯後的目標類。至此,聲明式事務管理就算是實現了。我們沒有對業務代碼進行任何操作,所有設置均在配置文件中完成,這就是聲明式事務的最大優點
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章