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的事务管理器分别对应PlatformTransactionManagerReactiveTransactionManager,本文只关注传统的事务管理器。
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 provided org.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包(事务管理功能)

021-springboot源码解读-自动配置三部曲01创建属于自己的spring boot autofigure

Spring 事务Transaction源码深度解析

Spring 事务Transaction源码深度解析

Spring Transaction源码分析

Spring-事务原理解读