Spring Transaction 源码解读
Posted T.Y.Bao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Transaction 源码解读相关的知识,希望对你有一定的参考价值。
Spring Transaction 规范的maven坐标如下:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>...</version>
</dependency>
该包提供了spring事务规范和默认的jta(java transaction api)实现(org.springframework.transaction.jta
包下),具体的实现要看不同的组件,如spring-jdbc提供了数据库的事务实现。
Spring Transaction的核心接口为 事务管理器TransactionManager
,不过该接口为标识接口,标识实现类是传统或Reactive的事务管理器。传统和Reactive的事务管理器分别对应PlatformTransactionManager
和ReactiveTransactionManager
,本文只关注传统的事务管理器。
spring-tx对传统的事务管理器PlatformTransactionManager
提供了抽象实现AbstractPlatformTransactionManager
,一般自定义事务管理器推荐继承该AbstractPlatformTransactionManager
,如spring-jdbc的DataSourceTransactionManager
就继承该抽象类。spring-tx事务管理器的uml类图如下:
关于spring事务的官方规范可以参考:Spring Transaction Management
PlatformTransactionManager
来看看该接口的注释说明:
central interface in Spring’s imperative transaction infrastructure. Typically, applications will work with either
TransactionTemplate
or declarative transaction demarcation through AOP. It is recommended to derive from the providedorg.springframework.transaction.support.AbstractPlatformTransactionManager
class, which pre-implements the defined propagation behavior and takes care of transaction synchronization handling.
public interface PlatformTransactionManager extends TransactionManager
// 根据指定的事务传播方式来决定返回正在运行的事务或新建一个事务
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
// 根据TransactionStatus提交事务,如果该事务被标记为rollback-only则执行回滚
// 如果当前事务为嵌套的内层事务,则根据事务传播方式会忽略当前提交
void commit(TransactionStatus status) throws TransactionException;
// 实施回滚
// 如果当前事务不是新事务(即嵌套事务),只需根据不同的事务传播方式设置外层事务的rollback-only属性。
// Do not call rollback on a transaction if commit threw an exception.
void rollback(TransactionStatus status) throws TransactionException;
TransactionStatus
代表当前事务执行的状态。如果是声明式事务,事务状态信息存储在ThreadLocal
中,参见TransactionAspectSupport
,可通过静态方法TransactionAspectSupport#currentTransactionStatus
获取当前事务状态。
AbstractPlatformTransactionManager
Abstract base class that implements Spring’s standard transaction workflow
该抽象类提供了以下工作流处理:
- 判断是否存在事务
- 应用事务传播方法
- 暂停或恢复事务
- 提交时检查rollback-only标识
- 对回滚做适当修改(直接回滚?还是设置rollback-only标识)
- 调用事务同步器回调方法(如果同步器开启)
关于事务同步器: Transaction synchronization is a generic mechanism for registering callbacks that get invoked at transaction completion time. This is mainly used internally by the data access support classes for JDBC, Hibernate, JPA, etc when running within a JTA transaction: They register resources that are opened within the transaction for closing at transaction completion time, allowing e.g. for reuse of the same Hibernate Session within the transaction. The same mechanism can also be leveraged for custom synchronization needs in an application.
事务同步器相当于一个事务扩展点,在事务的最后阶段提供了事务同步器的方法方便扩展,TransactionSynchronization
接口提供了四个回调方法#beforeCommit #beforeCompletion #afterCommit #afterCompletion
事务同步器由
TransactionSynchronizationManager
进行管理,所有的TransactionSynchronization
和Resource(如DataSource的Connection资源,Mybatis的SqlSession资源)都放在ThreadLocal
中,可以通过TransactionSynchronizationManager
的静态方法进行注册、获取 资源信息和TransactionSynchronization
继承该类,必须重写以下抽象方法:
doGetTransaction
doBegin
doCommit
doRollback
其他的方法不强制重写,可选 doSuspend,doResume, doSuspendSynchronization, doResumeSynchronization, doRollbackOnCommitException, doSetRollbackOnly, doCleanupAfterCompletion
编程式事务TransactionTemplate
TransactionTemplate
为我们提供了编程式事务的模板,需要调用编程式事务时只需调用TransactionTemplate#execute
或接口defaultTransactionOperations#executeWithoutResult
,分别对应有返回值和无返回值的情况。两类方法最后都会调用TransactionTemplate#execute
方法。
使用案例:
@Service
class TransactionService
// register somewhere
@Resource
private TransactionTemplate transactionTemplate;
@Resource
private OneMapper oneMapper;
@Resource
private TwoMapper twoMapper;
public void runSelfDefineTransaction()
transactionTemplate.setIsolationLevel(TransactionDefinition.PROPAGATION_REQUIRED);
transactionTemplate.setTimeout(5);
transactionTemplate.setReadOnly(false);
transactionTemplate.executeWithoutResult(
transactionStatus ->
oneMapper.insert(...);
twoMapper.insert(...);
);
TransactionTemplate
源码如下:
// 继承自TransactionDefinition,可修改配置
public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean
@Nullable
private PlatformTransactionManager transactionManager;
...
// 事务执行过程转化为TransactionCallback传入
@Override
@Nullable
public <T> T execute(TransactionCallback<T> action) throws TransactionException
...
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try
// 执行自定义事务操作
result = action.doInTransaction(status);
catch (RuntimeException | Error ex)
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
catch (Throwable ex)
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
// 提交
this.transactionManager.commit(status);
return result;
声明式事务
Spring声明式事务通过AOP实现,对注解了@Transactional
注解的方法添加拦截器(注意使用方式,不然不生效,如方法必须public、避免类内调用),在拦截器中调用TransactionManager
相关方法,参见TransactionInterceptor
。
关于AOP,可以参考Spring AOP及代理类执行顺序
由于事务的拦截器没有实现Ordered
接口、注解@Order
、注解@Priority
,所以默认最低优先级
声明式事务可以通过TransanctionAspectSupport
工具类获取当前正在运行的事务
以上是关于Spring Transaction 源码解读的主要内容,如果未能解决你的问题,请参考以下文章
#yyds干货盘点# mybatis源码解读:transaction包(事务管理功能)