事务是一组操作的原子执行,其中任何一笔操作失败将导致全部操作撤销。
什么是事务?
如上所言,事务遵循ACID原则,A是原子性(atomicity);B是一致性(consistency),事务执行前后涉及到的相关数据保持一致;C是隔离性(isolation),事务正确提交之前结果不应被其他事务所见;D是持久性(durability),执行结果得到持久保存。这对于金融系统和交易类业务处理系统至关重要。
面向单一事务资源(数据库或应用服务)的称之为本地事务,java可通过JDBC的Connection实现;面向多个事务资源的分布式同步管理的称之为全局事务,java可通过JTA按照XA的二阶段提交方式实现。
Spring事务管理方式
Spring事务管理框架对JDBC、JTA事务处理进行了更高一层抽象,向开发人员提供了统一的开发接口,面对本地事务和全局事务使用一种编程模型,从而大大降低了开发的复杂度。
在开发中使用spring进行事务管理,需要首先在配置文件中进行transactionManager的配置,然后通过编程方式或者声明方式调用事务处理。
1、配置transactionManager
本地事务
基于JDBC事务管理器配置示例如下:
dataSource属性指定需要事务管理的javax.sql.DataSource对象。
全局事务
大部分应用服务器容器提供JTA支持,配置好JNDI数据源和JtaTransactionManager即可。
"dataSource"表示从JNDI中获取数据源,"transactionManager"是JTA事务管理器,其中属性transactionManagerName是其JNDI命名。
Spring还提供了对特定应用服务器事务管理器集成的支持,如:WebLogicJtaTransactionManager、WebSphereUowTransactionManager、OC4JJtaTransactionManager。
Tomcat容器本身不支持JTA,但可以借助于第三方JTA管理器实现,如JOTM(Java Open Transaction Manager )或AtomikosTransactionsEssentials。
2、编程式
应用需要调用Spring提供的PlatformTransactionManager、TransactionDefinition 和 TransactionStatus 三个核心接口。下面以银行账户之间转账例子说明。
此外,Spring还提供了更为简化的TransactionTemplate开发接口。
3、声明式
声明式通过配置或注解方式将事务管理与业务逻辑代码独立,开发人员只需在配置文件中做相应的事务规则声明或注解,便可以将事务规则通过AOP横切应用到业务逻辑中。支持TransactionInterceptor、TransactionProxyFactoryBean多种配置方式,Spring 2.x 引入了 命名空间和基于 Annotation 的方式,使得事务规则的声明配置更为简单方便。
基于 命名空间的声明式事务管理
基于 @Transactional 的声明式事务管理
通过在业务处理接口、接口方法、类以及类方法上添加@Transactional注解便可实现事务配置。
在配置文件中仅仅需要开启注解开关
这两种方式各有优点:基于 的方式,可通过切点表达式批量匹配多个方法;基于@Transactional 注解方式更为简单明了。
Spring事务管理原理
Spring事务管理框架包括三层:接口层、实现层和适配层。
接口层面向应用和拦截类提供简单统一的访问接口;实现层实现了Spring事务管理框架的主要逻辑,并定义了子类的抽象方法;适配层通过实现框架类将各种持久层的访问类库统一集成到Spring的事务管理框架之中。
1、接口层
Spring事务管理框架通过PlatformTransactionManager、TransactionDefinition、TransactionStatus接口向上层应用提供事务处理控制方法(getTransaction、commit、rollback),其中TransactionDefination接口定义事务各种属性;TransactionStatus保存事务执行状态;PlatformTransactionManager是向上层应用提供事务处理方法的接口。详见图1,这些接口在spring-tx包中定义。
TransacctionDefinition对事务的各种传播行为和隔离级别进行了定义。
2、实现层
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变量,事务执行过程中所有方法都可以随时读取或修改当前事务的执行上下文。这样设计与事务处理的原子性保持了一致,任何时候都仅仅处于一个最小事务提交之中。
3、适配层
Spring在适配层继承实现AbstractPlatformTransactionManager类等,集成各种访问数据源或者消息中间件的类库,包括:
事务管理器类
小结
Spring事务管理框架简单易用、方便集成,它使得用户可以不用再关注事务处理的繁琐细节,而更专注于业务逻辑。另外,Spring事务管理框架本身的分层设计思想也很值得学习借鉴。
本文作者:孙兆玉,点融FinCore团队资深软件开发工程师,擅长Web后端开发,平时热爱钻研新技术,对分布式计算和数据管理很感兴趣。