分享
 
 
 

技术分享 在Spring中实现事务挂起(图)

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

摘要

SPRing Framework是一个流行的java/J2EE应用框架,它构建于一个轻量级的反向控制(Inversion-of-Control,QoC)模式的容器的基础之上,以其数据访问和事务治理能力而著称。Spring的声明性事务划分适用于任何的POJO(pure old java object或plain ordinary Java object,无格式普通Java对象)目标对象,其声明性事务如同EJB容器托管事务(Container-Managed Transaction,CMT)一样完善。后端事务治理器的选择包括简单的基于JDBC的事务和完善的J2EE事务(借助于JTA策略)。

本文具体讨论了Spring的事务治理功能。重点介绍了如何以JTA作为后端事务策略,使用Spring的针对POJO的声明性事务。本文说明了Spring的事务服务可以与J2EE服务器的事务协调程序(如BEA WebLogic Server的事务协调程序)进行无缝交互,实际上已经成为EJB CMT的传统事务划分方式的替代方案。

针对POJO的声明性事务

为了说明Spring的声明性事务划分方式,让我们来看看Spring的PetClinic示例应用程序的中心服务外观(facade)的配置:

<bean id="dataSource"

class="org.springframework.jndi.JndiObjectFactoryBean"

<property name="jndiName"

<valuejava: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位置--这将从J2EE服务器托管的JNDI环境中获取指定的DataSource。

一个PlatformTransactionManage实现--在本例中,该实现指定Spring的JtaTransactionManager,它委托给J2EE服务器的事务协调程序。

应用程序服务实现--这是一个简单的POJO,它封装了业务和数据访问逻辑。它实现应用程序的Clinic服务接口。

一个应用程序服务的事务代理--该代理定义了目标服务的事务属性,提供具体的方法命名模式,并创建相应的事务。对于实际的事务治理,代理指向PlatformTransactionManager实现。

注重:Spring还通过通用属性(Commons Attribute)或者J2SE 5.0的注释(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 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager),或者通过JTA支持嵌套事务。

事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务。这是一个最优化提示。在一些情况下,一些事务策略能够起到显著的最优化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)时避免dirty checking(试图“刷新”)。

在事务属性中还有定义“timeout”值的选项,指定事务超时为几秒。在JTA中,这将被简单地传递到J2EE服务器的事务协调程序,并据此得到相应的解释。

使用事务代理

在运行时,客户端将获取到“clinic”bean的引用,将其转换为Clinic接口,同时在它上面调用诸如loadPet或storePet之类的操作。这将隐式地使用在目标对象之前注册的“事务拦截器”检查Spring的事务代理;新的事务将被创建,然后调用将被委派给JdbcClinic目标方法。

图1说明了一个具有“advisor链”和终端目标的AOP代理的底层概念。其中,唯一的advisor就是将事务行为包装到目标方法的事务拦截器。这是在Spring的声明性事务功能的帮助下产生的基于代理的AOP(面向方面编程)。

图1. 具有“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

<

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有