如上所言,事务遵循ACID原则,A是原子性(atomicity);B是一致性(consistency),事务执行前后涉及到的相关数据保持一致;C是隔离性(isolation),事务正确提交之前结果不应被其他事务所见;D是持久性(durability),执行结果得到持久保存。这对于金融系统和交易类业务处理系统至关重要。
面向单一事务资源(数据库或应用服务)的称之为本地事务,java可通过JDBC的Connection实现;面向多个事务资源的分布式同步管理的称之为全局事务,java可通过JTA按照XA的二阶段提交方式实现。
Spring事务管理框架对JDBC、JTA事务处理进行了更高一层抽象,向开发人员提供了统一的开发接口,面对本地事务和全局事务使用一种编程模型,从而大大降低了开发的复杂度。
在开发中使用spring进行事务管理,需要首先在配置文件中进行transactionManager的配置,然后通过编程方式或者声明方式调用事务处理。
- 本地事务
基于JDBC事务管理器配置示例如下:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
- 1
- 2
- 3
dataSource属性指定需要事务管理的javax.sql.DataSource
对象。
- 全局事务
大部分应用服务器容器提供JTA支持,配置好JNDI数据源和JtaTransactionManager
即可。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd">
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/test" />
<bean id="transactionManager" class="org.springframework.transication.JtaTransactionManager">
<property name="transactionManagerName" value="java:comp/TransactionManager" />
</bean>
</beans>
“dataSource
“表示从JNDI中获取数据源,”transactionManager
“是JTA事务管理器,其中属性transactionManagerName
是其JNDI命名。
Spring还提供了对特定应用服务器事务管理器集成的支持,如:WebLogicJtaTransactionManager
、WebSphereUowTransactionManager
、OC4JJtaTransactionManager
。
Tomcat容器本身不支持JTA,但可以借助于第三方JTA管理器实现,如JOTM(Java Open Transaction Manager )或AtomikosTransactionsEssentials
。
应用需要调用Spring提供的PlatformTransactionManager
、TransactionDefinition
和TransactionStatus
三个核心接口。下面以银行账户之间转账例子说明。
public class BankServiceImpl implements BankService {
private BankDao bankDao;
private TransactionDefinition txDefinition;
private PlatformTransactionManager txManager;
public boolean transfer(long fromId, long toId, BigDecimal amount){
Transaction txStatus = txManager.getTransaction(txDefinition);
boolean result = false;
try{
result = bankDao.transfer(fromId, toId, amount);
txManager.commit(txStatus);
} catach(){
result = false;
txManager.rollback(txStatus);
}
return result;
}
}
此外,Spring还提供了更为简化的TransactionTemplate
开发接口。
声明式通过配置或注解方式将事务管理与业务逻辑代码独立,开发人员只需在配置文件中做相应的事务规则声明或注解,便可以将事务规则通过AOP横切应用到业务逻辑中。支持TransactionInterceptor、TransactionProxyFactoryBean多种配置方式,Spring 2.x 引入了 命名空间和基于 Annotation 的方式,使得事务规则的声明配置更为简单方便。
- 基于 命名空间的声明式事务管理
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/context/spring-aop.xsd">
<description>数据源及事务配置</description>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transfer" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 配置哪些方法参与事务 -->
<aop:config>
<aop:pointcut id="allMethod" expression="execution(* service.*.*(..))"/>
<aop:advisor pointcut-ref="allMethod" advice-ref="txAdvice"/>
</aop:config>
</beans>
- 基于 @Transactional 的声明式事务管理
通过在业务处理接口、接口方法、类以及类方法上添加@Transactional注解便可实现事务配置。
@Transactional(propagation = Propagation.REQUIRED)
public boolean transfer(long fromId, long toId, BigDecimal amount){
return bankDao.transfer(fromId, toId, amount);
}
在配置文件中仅仅需要开启注解开关
<tx:annotation-driven transaction-manager="transactionManager" />
- 1
这两种方式各有优点:基于 <tx>
的方式,可通过切点表达式批量匹配多个方法;基于@Transactional 注解方式更为简单明了。
Spring事务管理框架包括三层:接口层、实现层和适配层。
接口层面向应用和拦截类提供简单统一的访问接口;实现层实现了Spring事务管理框架的主要逻辑,并定义了子类的抽象方法;适配层通过实现框架类将各种持久层的访问类库统一集成到Spring的事务管理框架之中。
Spring事务管理框架通过PlatformTransactionManager、TransactionDefinition、TransactionStatus接口向上层应用提供事务处理控制方法(getTransaction、commit、rollback),其中TransactionDefination接口定义事务各种属性;TransactionStatus保存事务执行状态;PlatformTransactionManager是向上层应用提供事务处理方法的接口。详见图1,这些接口在spring-tx包中定义。
TransacctionDefinition对事务的各种传播行为和隔离级别进行了定义。
Spring事务管理框架按照”1)接口层”的定义在
org.springframework.transaction.support
包中提供了实现类,主要包括:
AbstractPlatformTransactionManager
、DefaultTransactionDefinition
、DefaultTransactionStatus
、SuspendedResourceHolder
、TransactionSynchronizationManager
等。AbstractPlatformTransactionManager
、DefaultTransactionDefinition
、DefaultTransactionStatus
分别继承实现了PlatformTransactionManager
、TransactionDefinition
、TransactionStatus
接口。
如图2中所示,AbstractPlatformTransactionManager
实现了多事务处理的主要逻辑,其中私有方法suspend(Object transaction)
和resume(Object transaction,SuspendedResourcesHolder resourcesHolder)
实现了对嵌套事务的外部事务进行调度管理,suspend
方法在getTransaction
调用中被触发,resume
方法在commit
和rollback
调用中被触发。
AbstractPlatformTransactionManager
类中定义的一系列doXXX方法(如: doGetTransaction
等)是对底层不同事务处理具体实现方法的封装,具体实现类需要实现这些方法(如:DataSourceTransactionManager
)。这些方法中定义的Object transaction
和Object suspendedResources
两个参数是关键数据,transaction相当于实现层内部定义使用的transactionStatus
类,suspendedResources
是实现层定义的相关资源类,它们都是Object类型,AbstractPlatformTransactionManager
只对它们的值进行保存和传递,DefaultTransactionStatus
中定义的两个属性对之对应。
SuspendedResourceHolder
类是对嵌套事务的当前外部事务的资源暂存,对应保存在当前DefaultTransactionStatus
中的suspendedResources
属性。
图3中,TransactionSynchronizationManager
是当前事务处理的上下文数据管理类,resources是当前事务所使用到的资源,如:DataSourceTransactionManager
用于保存对应数据源的ConnectionHolder
;synchronizations
管理事务处理过程中各阶段各种资源所需要做的同步处理操作,如:ConnectionSynchronization
事务执行过程中对链接的绑定与解绑,SpringLobCreatorSynchronization
在事务结束时对Lob对象进行关闭。
TransactionSynchronizationManager
与图2中SuspendedResourceHolder
具有对应的属性,前者是保存当前事务的执行上下文;后者则是被暂停的外部事务的执行上下文,当前事务commit或rollback之后,后者的值就被恢复到TransactionSynchronizationManager
。
TransactionSynchronizationManager
所有属性都是静态ThreadLocal
变量,事务执行过程中所有方法都可以随时读取或修改当前事务的执行上下文。这样设计与事务处理的原子性保持了一致,任何时候都仅仅处于一个最小事务提交之中。
Spring在适配层继承实现AbstractPlatformTransactionManager类等,集成各种访问数据源或者消息中间件的类库,包括:
事务管理器类 | 说明 |
---|---|
DataSourceTransactionManager | 位于org.springframework.jdbc.datasource包中,提供对单个javax.sql.DataSource事务管理 |
JdoTransactionManager | 位于org.springframework.orm.jdo包中,提供对单个javax.jdo.PersistenceManagerFactory事务管理 |
JpaTransactionManager | 位于org.springframework.orm.jpa包中,提供对单个javax.persistence.EntityManagerFactory事务支持 |
HibernateTransactionManager | 位于org.springframework.orm.hibernate3包中,提供对单个org.hibernate.SessionFactory事务支持 |
JtaTransactionManager | 位于org.springframework.transaction.jta包中,提供对分布式事务管理的支持,并将事务管理委托给Java EE应用服务器事务管理器 |
OC4JjtaTransactionManager | 位于org.springframework.transaction.jta包中,Spring提供的对OC4J10.1.3+应用服务器事务管理器的适配器 |
WebSphereUowTransactionManager | 位于org.springframework.transaction.jta包中,Spring提供的对WebSphere 6.0+应用服务器事务管理器的适配器 |
WebLogicJtaTransactionManager | 位于org.springframework.transaction.jta包中,Spring提供的对WebLogic 8.1+应用服务器事务管理器的适配器 |
Spring事务管理框架简单易用、方便集成,它使得用户可以不用再关注事务处理的繁琐细节,而更专注于业务逻辑。另外,Spring事务管理框架本身的分层设计思想也很值得学习借鉴。