摘要 Spring Framework是一個流行的Java/J
EE應用框架
它構建於一個輕量級的反向控制(Inversion
of
Control
QoC)模式的容器的基礎之上
以其數據訪問和事務管理能力而著稱
Spring的聲明性事務劃分適用於任何的POJO(pure old java object或plain ordinary Java object
無格式普通Java對象)目標對象
其聲明性事務如同EJB容器托管事務(Container
Managed Transaction
CMT)一樣完善
後端事務管理器的選擇包括簡單的基於JDBC的事務和完善的J
EE事務(借助於JTA策略)
本文詳細討論了Spring的事務管理功能
重點介紹了如何以JTA作為後端事務策略
使用Spring的針對POJO的聲明性事務
本文說明了Spring的事務服務可以與J
EE服務器的事務協調程序(如BEA WebLogic Server的事務協調程序)進行無縫交互
實際上已經成為EJB CMT的傳統事務劃分方式的替代方案
針對POJO的聲明性事務 為了說明Spring的聲明性事務劃分方式
讓我們來看看Spring的PetClinic示例應用程序的中央服務外觀(facade)的配置
<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>
它遵從了Spring的標准XMLBean定義格式
它定義了
一個DataSource引用
指向一個JNDI位置
這將從J
EE服務器托管的JNDI環境中獲取指定的DataSource
一個PlatformTransactionManage實現
在本例中
該實現指定Spring的JtaTransactionManager
它委托給J
EE服務器的事務協調程序
應用程序服務實現
這是一個簡單的POJO
它封裝了業務和數據訪問邏輯
它實現應用程序的Clinic服務接口
一個應用程序服務的事務代理
該代理定義了目標服務的事務屬性
提供具體的方法命名模式
並創建相應的事務
對於實際的事務管理
代理指向PlatformTransactionManager實現
注意
Spring還通過通用屬性(Commons Attribute)或者J
SE
的注釋(annotation)
支持一種自動代理機制和對源級(source
level)元數據的使用
作為顯示代理定義的替代方案
這些替代方案不在本文的討論范圍之內
其詳細資料請參考Spring說明文檔
使用的服務接口和服務實現是特定於應用程序的
無需了解Spring(具體說是Spring的事務管理)就可以實現
純Java對象可以用作目標對象
而任何一個純Java接口都可以用作服務接口
下面是一個Clinic接口的例子
public interface Clinic {
Pet loadPet(int id);
void storePet(Pet pet);
}
下面顯示了該接口的一個簡單實現
假定它使用JDBC來執行必要的數據訪問
它通過一個bean屬性的setter方法接收JDBC DataSource
這直接對應上面配置中的dataSource屬性定義
public class JdbcClinic implements Clinic {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this
dataSource = dataSource;
}
public Pet loadPet(int id) {
try {
Connection con = this
dataSource
getConnection();
}
catch (SQLException ex) {
}
}
public void storePet(Pet pet) {
try {
Connection con = this
dataSource
getConnection();
}
catch (SQLException ex) {
}
}
}
正如您所看到的
代碼簡單明了
使用了一個簡單Java對象
事務管理由事務代理處理
我們隨後再對其進行說明
注意
PetClinic示例應用程序中實際的基於JDBC的Clinic實現利用了Spring的JDBC支持類
以免只工作在簡單的JDBC API級別上
但是
Spring的事務管理還將使用簡單的基於JDBC的實現
比如上面的實現
定義事務代理 除JdbcClinic實例之外
配置還為其定義了一個事務代理
如果需要
可以顯式地指定該事務代理所暴露的實際接口
默認狀態下
目標對象實現的所有接口都將被暴露
在本例中是應用程序的Clinic服務接口
從客戶端的角度來看
clinic
bean只是應用程序的Clinic接口的實現
客戶端不必知道自己正在和事務代理打交道
這就是接口的力量
目標對象的直接引用可以很輕松地由實現了相同接口的代理取代
在本例中是一個隱式地創建事務的代理
對於特定的方法或方法命名模式
代理的具體事務行為由事務屬性驅動
如下面的例子所示
<prop key=
load*
>PROPAGATION_REQUIRED
readOnly</prop><prop key=
store*
>PROPAGATION_REQUIRED</prop>
key屬性確定代理應該給哪個方法增加事務行為
這樣的屬性最重要的部份是傳播行為
有以下選項可供使用
PROPAGATION_REQUIRED
支持當前事務
如果當前沒有事務
就新建一個事務
這是最常見的選擇
PROPAGATION_SUPPORTS
支持當前事務
如果當前沒有事務
就以非事務方式執行
PROPAGATION_MANDATORY
支持當前事務
如果當前沒有事務
就拋出異常
PROPAGATION_REQUIRES_NEW
新建事務
如果當前存在事務
把當前事務掛起
PROPAGATION_NOT_SUPPORTED
以非事務方式執行操作
如果當前存在事務
就把當前事務掛起
PROPAGATION_NEVER
以非事務方式執行
如果當前存在事務
則拋出異常
PROPAGATION_NESTED
如果當前存在事務
則在嵌套事務內執行
如果當前沒有事務
則進行與PROPAGATION_REQUIRED類似的操作
前六個策略類似於EJB CMT
常量名相同
因此
對EJB開發人員來說
應該立刻就感到熟悉
第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量
它要求事務管理器或者使用JDBC
Savepoint API提供嵌套事務行為(如Spring的DataSourceTransactionManager)
或者通過JTA支持嵌套事務
事務屬性中的readOnly標志表示對應的事務應該被最優化為只讀事務
這是一個最優化提示
在一些情況下
一些事務策略能夠起到顯著的最優化效果
例如在使用Object/Relational映射工具(如
Hibernate或TopLink)時避免dirty checking(試圖
刷新
)
在事務屬性中還有定義
timeout
值的選項
指定事務超時為幾秒
在JTA中
這將被簡單地傳遞到J
EE服務器的事務協調程序
並據此得到相應的解釋
使用事務代理 在運行時
客戶端將獲取到
clinic
bean的引用
將其轉換為Clinic接口
同時在它上面調用諸如loadPet或storePet之類的操作
這將隱式地使用在目標對象之前注冊的
事務攔截器
檢查Spring的事務代理
新的事務將被創建
然後調用將被委派給JdbcClinic目標方法
圖
說明了一個具有
advisor鏈
和終端目標的AOP代理的底層概念
其中
唯一的advisor就是將事務行為包裝到目標方法的事務攔截器
這是在Spring的聲明性事務功能的幫助下產生的基於代理的AOP(面向方面編程)
educitycn/img_///jpg >
圖 具有advisor鏈和終端目標的AOP代理 例如
PetClinic web應用程序中的web層組件能夠執行ServletContext查詢操作來獲取對Spring WebApplicationContext的引用
然後獲得那裡托管的
Clinic
bean
WebApplicationContext ctx =
WebApplicationContexUtils
getWebApplicationContext(servletContext);
Clinic clinic = (Clinic) ctx
getBean(
clinic);
Pet pet = new Pet();
pet
setName(
my new cat
);
clinic
storePet(pet); 在storePet()調用的開始
Spring的事務代理將隱式地創建一個事務
在storePet()調用返回時
將提交或回滾事務
默認情況下
任何RuntimeException或Error的拋出均會導致回滾
可以指定何時提交和何時回滾的實際規則
Spring的事務屬性支持一個稱為
回滾規則
的概念
例如
我們可以引入一個檢查性的PetClinicException
並告訴事務代理
在拋出該異常時執行進行回滾
<prop key=
load*
>PROPAGATION_REQUIRED
readOnly
PetClinicException</prop>
<
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28657.html