老王读Spring Transaction-4Spring事务管理的核心原理——PlatformTransactionManager&TransactionStatus
Posted 老王学源码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了老王读Spring Transaction-4Spring事务管理的核心原理——PlatformTransactionManager&TransactionStatus相关的知识,希望对你有一定的参考价值。
@TOC
前言
通过编程的方式实现一个事务管理的过程可以分为三步:
- begin: 获取连接
- commit: 提交事务(业务正常执行)
- rollback: 回滚事务(业务异常)
Spring 中通过 @Transactional
注解的方式实现了切面式的事务管理,其本质还是会经历上面三个步骤。
下面我们就来研究一下 Spring 中是怎么实现事务的管理的。
Spring 版本
spring-tx 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)
正文
Spring 中通过 PlatformTransactionManager
来实现事务的管理。
PlatformTransactionManager
PlatformTransactionManager 是 Spring 事务实现的核心接口。
通常,我们会通过 @Transactional
的方式 或者 TransactionTemplate
编程式的方式来使用 PlatformTransactionManager
。
PlatformTransactionManager 提供了三个方法用来管理事务:
- getTransaction(TransactionDefinition)
- commit(TransactionStatus)
- rollback(TransactionStatus)
PlatformTransactionManager 的源码如下:
public interface PlatformTransactionManager extends TransactionManager
/**
* 根据指定的事务传播行为,返回当前活动的事务或创建新事务。
* 注意: 隔离级别 或 timeout 等参数只会应用到新开启的事务上,因此,如果是加入到当前活动事务时,这些参数将会被忽略。
* @param TransactionDefinition 用于描述 事务传播行为、隔离级别、timeout 等
* @return TransactionStatus 表示当前事务
* @see TransactionDefinition#getPropagationBehavior
* @see TransactionDefinition#getIsolationLevel
* @see TransactionDefinition#getTimeout
*/
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
/**
* 提交给定的 TransactionStatus。
* 如果事务已通过编程方式标记为 rollback-only,将会执行回滚。
* 如果事务不是一个新开启的事务,则忽略本次提交操作(因为事务可能嵌套,嵌套在内部的事务在执行 commit 操作时,是不需要真正执行 commit 的)。
* @param getTransaction() 方法返回的 TransactionStatus 对象
*/
void commit(TransactionStatus status) throws TransactionException;
/**
* 回滚给定的 TransactionStatus。
* 如果事务不是新开启的事务,则只将事务标记为 rollback-only。
* @param getTransaction() 方法返回的 TransactionStatus 对象
*/
void rollback(TransactionStatus status) throws TransactionException;
PlatformTransactionManager 接口主要是通过 AbstractPlatformTransactionManager
来实现的。
AbstractPlatformTransactionManager 是实现 Spring 标准事务工作流的抽象基类,它是 DataSourceTransactionManager、JtaTransactionManager 等具体的平台事务管理器的基础。
TransactionStatus
TransactionStatus接口
TransactionStatus 能够获取事务的状态信息,它为事务代码提供了一种控制事务执行和查询事务状态的简单方法。
比如:它可以获取到当前是否是一个新开启的事务、事务有没有完成 等
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable
@Override
boolean isNewTransaction();
boolean hasSavepoint();
// 这里可以控制事务执行的行为。其他方法都是获取事务的状态信息。
@Override
void setRollbackOnly();
@Override
boolean isRollbackOnly();
void flush();
@Override
boolean isCompleted();
DefaultTransactionStatus
DefaultTransactionStatus 是 TransactionStatus 接口的默认实现。它由 PlatformTransactionManager 使用,保存了 AbstractPlatformTransactionManager 内部需要的所有状态信息。
DefaultTransactionStatus 的构造函数如下:
public DefaultTransactionStatus(
@Nullable Object transaction, boolean newTransaction, boolean newSynchronization,
boolean readOnly, boolean debug, @Nullable Object suspendedResources)
this.transaction = transaction; // 当前事务对象(可为 null)
this.newTransaction = newTransaction; // 是否需要新开启一个事务
this.newSynchronization = newSynchronization; // 是否需要开启新的事务同步
this.readOnly = readOnly; // 是否只读
this.debug = debug;
this.suspendedResources = suspendedResources; // 当前挂起的事务(可为 null)
Spring 在每进入一个 @Transactional 方法时,都会创建一个 TransactionStatus
对象: DefaultTransactionStatus
,用于记录本次事务的状态信息。
TransactionStatus 可以代表新事务,也可以代表现有的事务。
TransactionStatus 与 PlatformTransactionManager 结合使用
TransactionStatus
可以获取事务的状态信息,但是它并不负责事务的管理(提交 or 回滚)。
Spring 是通过 PlatformTransactionManager
来实现事务的管理的,其中提交 或 回滚事务都是以 TransactionStatus 做为入参的。
PlatformTransactionManager 管理事务的两种使用方式
PlatformTransactionManager 提供了事务管理的能力,而 Spring 提供了两种方式来调用 PlatformTransactionManager 来实现事务管理:一是,@Transactional 注解的方式;二是,TransactionTemplate 编程的方式。
TransactionTemplate 编程的方式
使用 TransactionTemplate 编程的方式来使用事务的话,可以使用类似如下的代码:
transactionTemplate.execute(new TransactionCallbackWithoutResult()
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus)
String sql = "insert into t_stu(id,name) values(?,?)";
jdbcTemplate.update(sql,1,"张三");
);
很显然,这样方式是使用了模板方法的模式,让 TransactionTemplate 去执行具体的事务管理操作,用户只需要填充业务代码就可以了。
TransactionTemplate#execute()
的源码如下:
// TransactionTemplate#execute()
public <T> T execute(TransactionCallback<T> action) throws TransactionException
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager)
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
else
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try
// 在事务中执行业务操作
result = action.doInTransaction(status);
catch (RuntimeException | Error ex)
// 判断是否要对 RuntimeException 和 Error 进行回滚
rollbackOnException(status, ex);
throw ex;
catch (Throwable ex)
// 判断是否要对 Throwable 进行回滚
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
// 业务操作正常结束,则执行 commit 操作
this.transactionManager.commit(status);
return result;
可以看到,处理流程如下:
- 通过 PlatformTransactionManager 获取到 TransactionStatus
- 在事务中执行业务方法
- 业务方法正常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 commit
- 业务方法异常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 rollback
@Transactional 注解的方式
@Transactional 的方式来自动管理事务,底层是通过 Spring AOP 来实现的。
前面在分析 @Transactional 的实现原理时 讲到:Spring 是通过 TransactionInterceptor
来自动实现事务拦截的。
TransactionInterceptor 会调用父类的 TransactionAspectSupport#invokeWithinTransaction()
方法来执行事务方法,代码如下:
可以看到,@Transactional 的处理流程如下:
- 创建 TransactionInfo 对象,包含: TransactionStatus、PlatformTransactionManager 等信息
- 执行业务方法
- 业务方法正常结束,则执行 commit
- 业务方法异常结束,则执行 rollback
TransactionAspectSupport 中关于事务的操作,都是通过 PlatformTransactionManager 来进行的,比如:TransactionAspectSupport#commitTransactionAfterReturning()
会调用 PlatformTransactionManager#commit()
方法。
这样 Spring AOP 就与 PlatformTransactionManager 衔接起来了。
小结
PlatformTransactionManager
是 Spring 事务实现的核心接口,它和 TransactionStatus
共同来完成事务的管理。
TransactionStatus 主要是用来获取事务的状态信息,而 PlatformTransactionManager 是基于事务状态信息来提交 或 回滚事务。
PlatformTransactionManager 提供了三个方法用来管理事务:
- getTransaction(TransactionDefinition)
- commit(TransactionStatus)
- rollback(TransactionStatus)
Spring 对事务的管理流程如下:
- 通过 PlatformTransactionManager 获取到 TransactionStatus
- 在事务中执行业务方法
- 业务方法正常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 commit
- 业务方法异常结束,则通过 PlatformTransactionManager 对 TransactionStatus 执行 rollback
以上是关于老王读Spring Transaction-4Spring事务管理的核心原理——PlatformTransactionManager&TransactionStatus的主要内容,如果未能解决你的问题,请参考以下文章
老王读Spring IoC-5Spring IoC 小结——控制反转依赖注入
老王读Spring IoC-2Spring IoC之BeanDefinition扫描注册的原理
老王读Spring Transaction-4Spring事务管理的核心原理——PlatformTransactionManager&TransactionStatus
老王读Spring Transaction从EnableTransactionManagement顺藤摸瓜,研究@Transactional的实现原理
老王读Spring Transaction-6spring-tx与DataSource连接池整合的原理
#yyds干货盘点# 老王读Spring AOP-4Spring AOP 与Spring IoC 结合的过程 && ProxyFactory 解析