??xml version="1.0" encoding="utf-8" standalone="yes"?> 对spring
?jin)解的不够精通,q两天在解决jms异常的过E中发现Qspring中提供了(jin)jmsTrasactionManagerQ同样实C(jin)事务理接口。这L(fng)
自动的拦截器Q就可以象数据库一栯动控制事务。在同时配置?jin)JMS和数据库事务的时候,两者同时有效。这L(fng)l的消息和数据库事务p量的一致了(jin)Q?br>
版权声明QQ何获得Matrix授权的网站,转蝲时请务必以超链接形式标明文章原始出处和作者信息及(qing)本声?/span>
作?Juergen Hoeller;xMatrix
原文地址:http://dev2dev.bea.com/pub/a/2005/07/spring_transactions.html
中文地址:http://www.matrix.org.cn/resource/article/44/44054_Transaction+Spring.html
关键词:(x) Transaction Suspension Spring
摘要
Spring
框架是一个流行的Z轻量U控制反转容器的Java/J2EE应用框架Q尤其在数据讉K和事务管理方面的能力是众所周知的。Spring的声明性事务分?
可以应用CQ何POJO目标对象Qƈ且包含所有EJBZ容器理事务中的已声明事务。后台的事务理器支持简单的ZJDBC的事务和全功能的Z
JTA的J2EE事务?br>
q篇文章详细的讨Z(jin)Spring的事务管理特性。重Ҏ(gu)如何在用JTA作ؓ(f)后台事务{略的基上让POJO?
用Spring的声明性事务,q也昄?jin)Spring的事务服务可以无~地与J2EE服务器(如BEA WebLogic
Server的事务协调器Q的事务协调器进行交互,作ؓ(f)EJB CMT传统事务分离方式的一个替代者?br>
POJO的声明性事?/span>
作ؓ(f)Spring声明性事务分L式的样例Q让我们来看一下Spring的样例应用PetClinic的中?j)服务外观中的配|:(x)
清单1Q?/b><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定义格式。定义了(jin)Q?br>1、一个DataSource引用Q指向一个JNDI位置—在J2EE服务器管理下q将从JNDI环境中获取特定的DataSource?br>2、一个应用服务实现—这是一个POJOQ封装了(jin)业务和数据访问逻辑。在q里实现?jin)应用中的Clinic服务接口?br>3、一个应用服务的事务代理—这个代理ؓ(f)目标服务定义?jin)事务属性,匚w特定的方法名模式qؓ(f)之创建相应的事务。在实际的事务管理中Q代理指向一个PlatformTransactionManager实现?br>注意Q除?jin)显式的代理定义QSpringq支持自动代理机制和通过Commons Attributes或J2SE 5.0注解实现源程序的元数据使用。这些可选方法的讨论过?jin)本文的范围。可以参考Spring的文档来?jin)解相关l节?br>
业务接口和业务实现是特定于应用的q且不需要关?j)Spring或者Spring的事务管理。普通Java对象可以作ؓ(f)服务的目标对象,而且M普通Java接口可以作ؓ(f)服务的接口。下面是一个Clinic接口的示例:(x)
清单2Q?/b>public interface Clinic {
Pet loadPet(int id);
void storePet(Pet pet);
...
}
q个接口的实现如下显C,假设他用JDBC来执行必要的数据讉K。他通过bean属性的讄Ҏ(gu)来获取JDBC的DataSource;q与上面的配|中的dataSource属性定义相对应?br>清单3Q?/b>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对象Q而事务管理由事务代理来处理,q个我们?x)在下面讨论?br>注意在PetClinicCZ应用中实际的ZJDBC的Clinic实现利用?jin)Spring的JDBC支持cL避免直接使用JDBC的API。虽然Spring的事务管理也可以与普通的ZJDBC实现一起工作,向上面的示例?br>
定义事务代理
除了(jin)JdbcClinic实例以外Q配|中也定义了(jin)一个事务代理。如果愿意这个代理所暴露的实际接口也可以昑ּ定义。默认情况下Q所有由目标对象实现的接口都暴露出来Q在q个例子中就是应用的Clinic服务接口?br>
从客L(fng)的观Ҏ(gu)看,"clinic" bean只是q个应用的Clinic接口的实现。客L(fng)不需要知道这?x)被一个事务代理所处理。这是接口的能力:(x)一个直接的目标对象的引用可以容易的被一个实现相同接口的代理所代替—在q儿是一个隐式创Z务的代理?br>代理的具体事务行Z(x)׃ؓ(f)Ҏ(gu)特定的方法或Ҏ(gu)命名模式而定义的事务属性来驱动Q就像下面的例子所C:(x)
清单3Q?/b><prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="store*">PROPAGATION_REQUIRED</prop>
Key属性决定代理将为方法提供什么样的事务行为。这个属性的最重要部分是事务传播行ؓ(f)。下面是一些可选的属性|(x)
1、PROPAGATION_REQUIRED --支持当前的事务,如果不存在就创徏一个新的。这是最常用的选择?br>2、PROPAGATION_SUPPORTS --支持当前的事务,如果不存在就不用事务?br>3、PROPAGATION_MANDATORY --支持当前的事务,如果不存在就抛出异常?br>4、PROPAGATION_REQUIRES_NEW --创徏一个新的事务,q暂停当前的事务Q如果存在)(j)?br>5、PROPAGATION_NOT_SUPPORTED --不用事务,q暂停当前的事务Q如果存在)(j)?br>6、PROPAGATION_NEVER --不用事务,如果当前存在事务抛出异常?br>7、PROPAGATION_NESTED --如果当前存在事务׃为嵌入事务执行,否则与PROPAGATION_REQUIREDcM?br>
?
个事务策略与EJB的CMTcMQ而且使用相同的常量名Q因此对EJB开发h员来说是很亲切的。第7个策略PROPAGATION_NESTED?
Spring提供的一个变体:(x)他需要事务管理器(如DataSourceTransactionManager)提供cMJDBC3.0那样的保存点
API来嵌套事务行为或者通过
JTA支持嵌套事务?br>
事务属性中的readOnly标识指示相应的事务应该作Z个只M务来优化。这是一个优化提C:(x)一些事务策略在q种情况下可以得到很好的性能优化Q如使用ORM工具如Hibernate或TopLink旉免脏数据(g)查(“flush”尝试)(j)?br>
在事务属性中q有一个“timeout”选项来定义事务的时U数。在JTA中,q个属性会(x)单地传递给J2EE服务器的事务协调器ƈ被正地解释?br>
使用事务代理
?
q行Ӟ客户端会(x)取得一个“clinic”引用ƈ转换为Clinic接口Q然后调用如loadPet或storePetҎ(gu)。这隐式地使用?
Spring的事务代理,通过“事务解释器”在目标对象中注册;q样一个新的事务就创徏?jin),然后具体的工作就会(x)代理给JdbcClinic的目标方法?br>?CZ?jin)一个用“徏议链”ƈ到达最后目标的AOP代理的潜在概c(din)在q个CZ中,唯一的徏议是一个事务解释器用来包装目标Ҏ(gu)的事务行为。这是一U用来在声明性事务功能下使用的基于代理的AOP?br>
Figure 1. An AOP proxy with an advisor chain and a target at the end
例如Q一个PetClinic应用的WEB层组件可以执行ServletContext定位来获取Spring WebApplicationContext的引用ƈ且获取受理的“clinic”BEANQ?br>清单4Q?/b>WebApplicationContext ctx =
WebApplicationContexUtils.getWebApplicationContext(servletContext);
Clinic clinic = (Clinic) ctx.getBean("clinic);
Pet pet = new Pet();
pet.setName("my new cat");
clinic.storePet(pet);
?
调用storePet()之前QSpring的事务代理隐式地创徏一个事务。当storePet()调用q回Ӟ事务提交或回滚。缺省情况下M
RuntimeException或Error导致回滚。实际的提交或回滚可以是可以定义的:(x)Spring的事务属性支持“回滚规则”的概念?br>
例如Q我们可以可以引入一个强制的PetClinicExceptionq且告诉事务代理在抛出异常时回滚Q?br>清单5Q?/b><prop key="load*">PROPAGATION_REQUIRED,readOnly,-PetClinicException</prop>
<prop key="store*">PROPAGATION_REQUIRED,-PetClinicException</prop>
q儿也有一个类似的“提交规则”语法,指示特定的异常将触发一ơ提交?br>?
意上面示例的昑ּ定位引用的方法只是一U访问受Spring理BEAN的方法的变化Q可以用在Q何WEB资源如servlet或filter。在构徏?
于Spring自n的MVC框架ӞBEAN可以直接被注到WEB控制器中。当然也支持在如Struts, WebWork, JSF, and
Tapestry框架中访问Spring理BEAN。详情可以参考Spring的文档?br>
PlatformTransactionManager{略
Spring
事务支持的核?j)接口是org.springframework.transaction.PlatformTransactionManager。所?
Spring的事务分d能都?x)委托给PlatformTransactionManagerQ传l相应的TransactionDefinition?
例)(j)来做实际的事务执行。虽然PlatformTransactionManager接口可以直接调用Q但通常应用只需要配|一个具体的事务理器ƈ且?
q声明性事务来分离事务?br>
Spring提供几种不同的PlatformTransactionManager实现Q分为如下两个类别:(x)
1?
本地事务{略—支持单一资源的事务(通常是单个数据库Q,其包?
org.springframework.jdbc.datasource.DataSourceTransactionManager?
org.springframework.orm.hibernate.HibernateTransactionManager?br>2、全局事务理—支持可能跨多个资源的全局事务。其相应的类为org.springframework.transaction.jta.JtaTransactionManagerQ将事务委托l遵循JTA规范的事务协调器Q通常为J2EE服务器,但不是强制的Q?br>
PlatformTransactionManager
抽象的主要h(hun)值在于应用不再被l定在特定的事务理环境。相反,事务{略可以很容易地切换—通过选择不同?
PlatformTransactionManager实现cR这׃得应用代码与声明事务分离保持一_(d)而不需要考虑应用lg所使用的环境了(jin)?br>
?
如,应用的初始版本可能布|在Tomcat上,与单个Oracle数据库交互。这可以方便地利用Spring的事务分ȝ性,只要选择ZJDBC?
DataSourceTransactionManager作ؓ(f)使用的事务策略。Spring?x)分M务,而JDBC驱动?x)执行相应的原始JDBC事务?br>
?
同应用的另一个版本可能会(x)布v在WebLogic服务器上Q用两个Oracle数据库。应用代码和事务分离不需要改变。唯一不同的是选择作ؓ(f)
JtaTransactionManager事务{略Q让Spring来分M务而W(xu)ebLogic服务器的事务协调器来执行事务?br>
JTA UserTransaction与JTA TransactionManager比较
让我们来看一下Spring对JTA支持的细节。虽然ƈ非经帔R要考虑q个l节但了(jin)解相关的l节q有必要的。对单的用例如前面章节的CZQ标准的JtaTransactionManager定义已经_?jin)?br>~?
省的Spring
JtaTransactionManager讄?x)从标准JNDI位置QJ2EE规范所定义的java:comp/UserTransactionQ获?
JTA的javax.transaction.UserTransaction对象。这对大部分标准J2EE环境来说已经_?jin)?br>
然而,
~省的JtaTransactionManager不能执行事务暂停Q也是说不支持PROPAGATION_REQUIRES_NEW?
PROPAGATION_NOT_SUPPORTEDQ。原因就在于标准的JTA
UserTransaction接口不支持事务的暂停和恢复,而只支持开始和完成新的事务?br>
Z(jin)实现事务的暂停,需要一?
javax.transaction.TransactionManager实例Q他提供?jin)JTA定义的标准的暂停和恢复方法。不q的是,J2EE没有?
JTA TransactionManager定义标准的JNDI位置Q因此,我们需要用厂商自q定位机制?br>清单6Q?/b><bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName">
<value>vendorSpecificJndiLocation</value>
</property>
</bean>
J2EE
本质上没有考虑JTA
TransactionManager接口作ؓ(f)公共API的一部分。JTA规范自n定义?jin)将TransactionManager接口作ؓ(f)容器集成的想
法。虽然这是可以理解的Q但是JTA
TransactionManager的标准JNDI位置q是可以增加一定的价|特别是对轻量U容器如Spring,q样MJ2EE服务器就可以用统
一的方式来定位JTA TransactionManager?jin)?br>
不仅Spring的JtaTransactionManager可以?
讉K中获益,O/R映射工具如Hibernate, Apache OJB, and Kodo
JDO也能得到好处Q因Z们需要在JTA环境中执行缓存同步的能力Q释攄存意味着JTA事务的完成)(j)。这U注册事务同步的能力只有JTA
TransactionManager接口才能提供Q而UserTransaction是处理不?jin)的。因此,q些工具都需要实现自q
TransactionManager定位器?br>
为JTA
TransactionManager定义标准的JNDI位置是许多底层Y件供应商最期望J2EE实现的功能。如果J2EE5.0的规范制定团队能够认?
到这个特性的重要性就太好?jin)。幸q地是,高J2EE服务器如WebLogic Server已经考虑JTA
TransactionManager作ؓ(f)公共的API包含在扩展功能中?br>
在WebLogic JTA中实现Spring的事务分?/b>
在WebLogic
Server中,JTA
TransactionManager官方的JNDI位置定义为javax.transaction.TransactionManager。这个值可?
在Spring的JtaTransactionManager中作为“transactionManagerName”用。原则上q样可以在
WebLogic's
JTApȝ中实C务暂停了(jin)Q也是说支持PROPAGATION_REQUIRES_NEW和PROPAGATION_NOT_SUPPORTED?
为?br>
除了(jin)标准的JtaTransactionManager和其支持的通用配置选项外,Springq提供了(jin)一个专用的WebLogicJtaTransactionManager适配器来直接利用WebLogic的JTA扩展?br>
在n受自动探WebLogic的JTA TransactionManager的便利之外,他提供超标准JTA的三个重要特性:(x)
1、事务命名—暴露出Spring的事务名lWebLogic ServerQ得Spring事务在WebLogic的事务监听器可见。缺省的QSpring?x)用声明性事务的完整Ҏ(gu)名?br>2、每事务隔离U别—将Spring事务属性中定义的隔ȝ别应用到WebLogic JTA事务中。这使得每个事务都可以定义数据库的隔ȝ别,而这是标准JTA所不支持的?br>3、强制事务恢复—即使在暂停的事务被标识为回滚时也可以恢复。这需要用WebLogic的扩展TransactionManager接口来调用forceResume()Ҏ(gu)?br>
Figure 2. WebLogic Server's transaction monitor (click the image for a full-size screen shot)
Spring的WebLogicJtaTransactionManager有效Cؓ(f)ZSpring的应用提供了(jin)WebLogic Server事务理的全部功能。这使得Spring事务分离成ؓ(f)一U能与EJB CMT竟争的品,而且提供?jin)相同别的事务支持?br>
Spring and EJB CMT
?
上所C,Spring的POJO声明性事务分d以作ZU除传统EJB
CMTq外的选择。但是Spring与EJBq不是完成互斥的QSpring的应用上下文也可以作为EJB
façade的后台来理数据讉KQDAOQ和其他l纹理的业务对象?br>
在EJB情景中,事务是由EJB
CMT来驱动的。对Spring来说Q数据访问支持特性会(x)自动(g)到q样的环境ƈ且采用相应的事务。例如,Spring对Hibernate的支持能够提
供隐式的资源理Q即使是EJB驱动的事务,甚至可以在不需要修改Q何DAO代码的情况下提供相同的语义?br>Spring有效的解耦了(jin)DAO实现与实际的q行环境。DAO可以参与Spring的事务就像参与EJB CMT事务一栗这不仅化在其他环境中的重用Q而且更方便在J2EE容器外进行测试?br>
l论
Spring框架为J2EE和非J2EE环境提供?jin)全量的事务分离的特性,特别表现在POJO的声明性事务上。他用一U灵z而非侵入式的方式为非EJB环境中的事务分离提供?jin)便利。与EJB不同Q这L(fng)事务性POJO应用对象可以很容易的被测试和在J2EE容器外补重用?br>
Spring
提供?jin)各U事务策略,如JtaTransactionManager是用来代理J2EE服务器的事务协调器,而JDBC
DataSourceTransactionManager是用来ؓ(f)单的JDBC
DataSourceQ就是单一目标数据库)(j)执行事务。Spring可以很容易ؓ(f)不同的环境通过后台配置的简单修Ҏ(gu)调整事务{略?br>
越
标准的JTA支持QSpring为WebLogic
Server的JTA扩展提供?jin)完善的集成Q可以支持高U特性如事务监视和每事务隔离U别。通过对WebLogic
Server的特D支持,ZSpring的应用可以完全利用WebLogic Server的事务管理功能?br>
Spring事务分离是
EJB
CMT之外的另一U可选方式,特别是对那些ZPOJO的轻量架构。在那只是因为选择LSSBQ本地无状态会(x)话BEANQ来应用声明性事务的情况下,?
于Spring的POJO服务模型是一U可行的选择Q他提供?jin)非帔R层的灉|性、可试性和重用性?br>
资源
•JTA - The JTA specification JTA规范
•WebLogic JTA - Documentation of WebLogic's JTA extensions WebLogic JTA扩展文档
关于作?/span>
Juergen Hoeller是Spring框架的创始h之一
]]>
数据库的spring配置参见Q?a >http://steeven.cnblogs.com/archive/2005/06/14/174410.html
jms部分如下Q?br>
?Spring 框架定制资源理
![]() |
U别: 中 Claude Duguay , 高 J2EE 架构? Capital Stream Inc. 2005 q? 11 ? 24 ?/p> Spring 框架体pȝ构依赖性降x低,q且应用程序中的组成部分进行了(jin)具体化,但是应用E序仍然是需要管理的。幸q的是,Spring 1.2 包括高? JMX 集成支持Qƈ?JMX 为应用程序提供了(jin)一U实用的理基础架构。在本文中,Claude Duguay ?Spring JMX 更进一步,向?zhn)展示了(jin)如何?f)Ҏ(gu)和属性透明地增加通知事g。最后得到的代码使?zhn)可以监视状态变化,同时不会(x)搞ؕ Java?对象?/blockquote> |