SpringBoot源码专题-Transaction事务切面
自动配置
概述
@EnableTransactionManagement 开启自动事务
org.springframework.transaction.annotation.EnableTransactionManagement
无论是默认自动配置事务,还是手动添加注解开启事务,都会使用 @EnableTransactionManagement
注解。
默认自动配置
配置文件 org.springframework.boot.autoconfigure.AutoConfiguration.imports
与spring-autoconfigure-metadata.properties
。
- 文件路径
spring-boot-autoconfigure-2.7.18.jar!/META-INF/spring-autoconfigure-metadata.properties
。 - 文件路径
spring-boot-autoconfigure-2.7.18-sources.jar!/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
。
JDBC 数据源与事务相关自动配置类
- 全量相关类
org.springframework.boot.autoconfigure.jdbc.*
org.springframework.boot.autoconfigure.transaction.*
- 重点类
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
TransactionAutoConfiguration
JdkDynamicAutoProxyConfiguration 与 CglibAutoProxyConfiguration 均使用了注解 @EnableTransactionManagement
。
|
|
自动配置手动添加注解
EnableTransactionManagement
|
|
ProxyTransactionManagementConfiguration
|
|
|
|
AutoProxyRegistrar#registerBeanDefinitions 方法注册 AOP 类时,底层调用了 org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired。
仅允许注册下列三个 AutoProxyCreator 其中之一,优先级按顺序递增,即 AnnotationAwareAspectJAutoProxyCreator 的优先级是最高的。
这也是 proxyTargetClass 属性同时影响 @Transactional
和 @Async
的原因,因为它们底层会使用同一个类实例。
|
|
事务 AOP 相关类
Advisor
|
|
Interceptor
事务使用流程概述
简单使用流程
TransactionAttribute txAttr; // 获取事务属性。
PlatformTransactionManager txManager; // 获取事务管理器,依赖 txAttr。
TransactionStatus status = txManager.getTransaction(txAttr); // 开启事务,得到事务状态。依赖 txManager 和 txAttr。事务状态 status 可能被封装到 TransactionInfo 中。
//执行业务逻辑
txManager.commit(status)/txManager.(status); // 提交或回退事务
简单执行流程
- 外部调用
@Transactional
注解修饰的方法。 - org.springframework.transaction.interceptor.TransactionInterceptor#invoke 事务拦截器拦截方法。
- org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction 事务处理的主要逻辑。
- 事务前置处理
- 获取数据库连接
- 创建事务
- 事务同步
- 等
- invocation.proceedWithInvocation() 执行业务逻辑
- 事务后置处理
- 提交或者回退事务
- 释放数据库连接
- 事务同步
- 等
事务属性关键实现类
RuleBasedTransactionAttribute -> DefaultTransactionAttribute -> DefaultTransactionDefinition,TransactionAttribute -> TransactionDefinition
JdbcTransactionManager -> AbstractPlatformTransactionManager -> DataSourceTransactionManager -> PlatformTransactionManager -> TransactionManager
DefaultTransactionStatus -> AbstractTransactionStatus -> TransactionStatus -> TransactionExecution,SavepointManager
TransactionAspectSupport.TransactionInfo 存储了事务的所有信息。
事务的数据库连接使用流程
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
Connection newCon = obtainDataSource().getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
txObject.getConnectionHolder().setSynchronizedWithTransaction(true); // 标识连接资源跟事务同步
txObject.getConnectionHolder().setTransactionActive(true); // 标识激活事务
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
TransactionSynchronizationManager.setActualTransactionActive(true); // 真正激活事务
TransactionSynchronizationManager.initSynchronization(); // 初始化同步行为
数据库连接关键实现类
DataSourceTransactionManager.DataSourceTransactionObject -> JdbcTransactionObjectSupport -> SavepointManager,SmartTransactionObject
ConnectionHolder -> ResourceHolderSupport -> ResourceHolder
AbstractPlatformTransactionManager#transactionSynchronization = SYNCHRONIZATION_ALWAYS; // 始终激活事务同步,即使是空事务。
TransactionSynchronizationManager#actualTransactionActive // 标识当前是否有一个实际的事务处于活动状态,即示当前线程是否与一个实际的事务相关联。
事务流程详情
核心代码摘录
|
|
主流程
入口方法
- org.springframework.transaction.interceptor.TransactionInterceptor#invoke
- org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
流程
- org.springframework.transaction.interceptor.TransactionAspectSupport#getTransactionAttributeSource 获取事务属性处理器,自动配置的实现是 AnnotationTransactionAttributeSource。
- org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute 解析 @Transactional 注解获取事务属性。首先从方法找注解,其次从方法所在的类上找,最后从接口或者父类上找。此处限制仅支持 public 方法。
- 首先从缓存 AbstractFallbackTransactionAttributeSource#attributeCache 查询。
- org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute 查找 @Transactional 注解。此处限制仅支持 public 方法。
- 底层调用 org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement) 解析 @Transactional 注解,填充属性。
- org.springframework.transaction.interceptor.TransactionAspectSupport#determineTransactionManager 获取对应的事务管理器。
- 主逻辑如下:
- 首先将 @Transactional 注解的 qualifier 属性作为事务管理器 bean name 查找;
- 其次将 TransactionAspectSupport#transactionManagerBeanName (默认未配置,为 null)作为事务管理器 bean name 查找;
- 然后使用默认管理器 TransactionAspectSupport#transactionManager(默认未配置,为 null);
- 最后从 bean factory 中查找 TransactionManager.class 类型的实现类作为默认事务管理器;
- 获取后会存入缓存 TransactionAspectSupport#transactionManagerCache,后续将直接从缓存中查找;默认事务管理器在缓存中的 key 为
DEFAULT_TRANSACTION_MANAGER_KEY = new Object()
。
- org.springframework.transaction.interceptor.TransactionAspectSupport#asPlatformTransactionManager 强转PlatformTransactionManager
- org.springframework.transaction.interceptor.TransactionAspectSupport#methodIdentification(java.lang.reflect.Method, java.lang.Class, org.springframework.transaction.interceptor.TransactionAttribute) 获取切点名称(类名+方法名),后续将作为事务名称。
- org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary 创建事务,返回 TransactionInfo。方法 invokeWithinTransaction 并未直接使用 TransactionStatus 传递事务信息,而是封装为 TransactionInfo,该类记录了更多事务相关信息。
- 如果未主动指定事务名称,则使用 joinpointIdentification(类名称+方法名)。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction 创建事务,如果 TransactionAttribute 与 PlatformTransactionManager 不为空。为空则是非法事务。
- org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo 封装事务相关信息为 TransactionInfo,并绑定到当前线程。
- invocation.proceedWithInvocation() 执行业务逻辑
- org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing 业务逻辑执行抛出异常后的处理逻辑。
- org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo 清除线程中的事务信息
- org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#restoreThreadLocalStatus 重置 TransactionAspectSupport#transactionInfoHolder 状态。
- transactionInfoHolder.set(this.oldTransactionInfo); 恢复 oldTransactionInfo 与当前线程的绑定。
- org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning 业务逻辑执行成功后的处理逻辑,提交事务。
- 调用
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
提交事务。 - org.springframework.transaction.support.AbstractPlatformTransactionManager#commit 提交事务。
- 如果当前事务仅允许 rollback(
defStatus.isLocalRollbackOnly())
),则调用 processRollback 回退事务。org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback。 - 如果全局事务标识为仅允许 rollback,且本地事务非必须 commit,则调用 processRollback 回滚事务。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit 处理提交事务。
- 调用
- 返回结果,执行
return retVal;
。
分支 AbstractPlatformTransactionManager#processCommit
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit
功能
处理提交事务。
流程
- org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareForCommit 当前为空。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerBeforeCommit 如果
status.isNewSynchronization()
,触发 beforeCommit 回调逻辑。- org.springframework.transaction.support.TransactionSynchronizationUtils#triggerBeforeCommit
- for-each TransactionSynchronizationManager.getSynchronizations() 调用 TransactionSynchronization#beforeCommit 方法。
- MyBatis 当前有 1 个实现,JdbcTemplate 无实现。
- org.mybatis.spring.SqlSessionUtils.SqlSessionSynchronization#beforeCommit
- 在事务提交之前(在“beforeCompletion”之前)被调用。此回调并不意味着事务将真正被提交。即使此方法已被调用,仍可能发生回滚。主要作用诸如将 SQL 语句刷新到数据库中等。
- 底层调用 org.apache.ibatis.session.defaults.DefaultSqlSession#commit, org.apache.ibatis.executor.BaseExecutor#commit。
- 底层最终调用 org.mybatis.spring.transaction.SpringManagedTransaction#commit,此处忽略 commit,执行空逻辑,因此未提交事务。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerBeforeCompletion 如果
status.isNewSynchronization()
,触发 beforeCompletion 回调逻辑。- org.springframework.transaction.support.TransactionSynchronizationUtils#triggerBeforeCompletion
- for-each TransactionSynchronizationManager.getSynchronizations()) 调用 TransactionSynchronization#beforeCompletion 方法。
- MyBatis 当前有 1 个实现,JdbcTemplate 无实现。
- org.mybatis.spring.SqlSessionUtils.SqlSessionSynchronization#beforeCompletion 如果 session 无引用,则将 DefaultSqlSessionFactory-SqlSessionHolder 从当前线程解绑。
- org.springframework.transaction.support.TransactionSynchronizationManager#unbindResource 将 DefaultSqlSessionFactory-SqlSessionHolder 从当前线程解绑。
- org.apache.ibatis.session.defaults.DefaultSqlSession#close 关闭连接。
- 底层调用了 org.apache.ibatis.executor.BaseExecutor#close,org.springframework.jdbc.datasource.DataSourceUtils#doReleaseConnection。
- 最终调用 org.springframework.jdbc.datasource.ConnectionHolder#released,ConnectionHolder#currentConnection 置为空。
- 某些情况下会调用 Connection#close 方法,Spring 应当不涉及,忽略分析。
- org.apache.ibatis.session.defaults.DefaultSqlSession#closeCursors 关闭游标。
- 释放 Savepoint,如果存在。应该是处理嵌套事务的。
- 实际提交,如果是新事务。调用 org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit。
- 获取数据库连接,
txObject.getConnectionHolder().getConnection()
。 - 数据库连接提交事务,
con.commit()
,具体逻辑由数据源定义。当前使用 Hikari 线程池数据源,具体调用 com.zaxxer.hikari.pool.ProxyConnection#commit 方法。 ProxyConnection#commit
中调用delegate.commit()
实际提交事务。当前使用 H2 内置数据库,delegate 是 H2 数据库的 JDBC 实现。底层调用了 com.zaxxer.hikari.pool.ProxyConnection#commit,org.h2.jdbc.JdbcConnection#commit。
- 获取数据库连接,
- org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCommit 如果
status.isNewSynchronization()
,触发 afterCommit 回调逻辑。- org.springframework.transaction.support.TransactionSynchronizationUtils#triggerAfterCommit
- MyBatis 当前有 1 个实现,JdbcTemplate 无实现。
- org.springframework.transaction.support.TransactionSynchronizationAdapter#afterCommit 空实现。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#triggerAfterCompletion 如果
status.isNewSynchronization()
,触发 afterCompletion 回调逻辑。- org.springframework.transaction.support.TransactionSynchronizationUtils#invokeAfterCompletion
- MyBatis 当前有 1 个实现,JdbcTemplate 无实现。
- org.mybatis.spring.SqlSessionUtils.SqlSessionSynchronization#afterCompletion 后置清理,如果 SqlSessionHolder 仍然活跃,SqlSessionSynchronization#holderActive 为true,则解绑 SqlSessionFactory-SqlSessionHolder,调用 SqlSession#close 关闭连接。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#cleanupAfterCompletion 清空变量,释放连接等等。
TransactionSynchronizationManager.clear()
清空 TransactionSynchronizationManager 持有的信息。- org.springframework.jdbc.datasource.DataSourceTransactionManager#doCleanupAfterCompletion调用
TransactionSynchronizationManager.unbindResource
解绑 DataSource-ConnectionHolder 与当前线程的绑定。 - org.springframework.jdbc.datasource.DataSourceUtils#resetConnectionAfterTransaction(java.sql.Connection, java.lang.Integer, boolean) 重置 Connection,恢复隔离基本、只读等属性。
- org.springframework.jdbc.datasource.DataSourceUtils#releaseConnection 释放 Connection。
- org.springframework.jdbc.datasource.DataSourceUtils#doReleaseConnection
- org.springframework.jdbc.datasource.DataSourceUtils#doCloseConnection
- 当前使用 Hikari 线程池数据源,最终底层调用 com.zaxxer.hikari.pool.ProxyConnection#close。
- org.springframework.jdbc.datasource.ConnectionHolder#clear 清空 ConnectionHolder 持有的信息。
- 如果当前存在挂起的资源,
status.getSuspendedResources()
,则进行恢复,调用org.springframework.transaction.support.AbstractPlatformTransactionManager#resume
。主要恢复了 TransactionSynchronizationManager 中持有的信息。
补充知识
回调逻辑(同步行为)
有序调用
- beforeCommit
- beforeCompletion
- afterCommit
- afterCompletion
JdbcTemplate 无上述 4 种回调。
MyBatis 上述 4 种回调各有 1 个实现。
SqlSessionHolder#referenceCount
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
finally 和 catch 中均会调用 org.mybatis.spring.SqlSessionUtils#closeSqlSession,释放 SqlSessionHolder 中 referenceCount 的变量(即数值减一)。
org.mybatis.spring.SqlSessionTemplate.SqlSessionInterceptor#invoke
org.mybatis.spring.SqlSessionUtils#getSqlSession(org.apache.ibatis.session.SqlSessionFactory, org.apache.ibatis.session.ExecutorType, org.springframework.dao.support.PersistenceExceptionTranslator)
org.mybatis.spring.SqlSessionUtils#registerSessionHolder
org.springframework.transaction.support.ResourceHolderSupport#requested,请求 SqlSessionHolder 中 referenceCount 的变量(即数值加一)。
封装信息
事务信息主要封装在 TransactionInfo txInfo
数据库连接主要封装在 ConnectionHolder conHolder
事务信息关联数据库连接主要封装在 DataSourceTransactionObject txObject
其它 DefaultTransactionStatus status
重要分支
待补充分支
- 分支org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing 业务逻辑执行抛出异常后的处理逻辑。
- 分支 org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback 处理回滚逻辑。
- 分支 org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction 如果当前线程已存在事务,后续处理逻辑。
分支 AbstractPlatformTransactionManager#getTransaction
功能
创建事务
主流程
- org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction 获取事务。
- new DataSourceTransactionObject 主要封装了数据库连接信息。
- org.springframework.jdbc.datasource.DataSourceTransactionManager#obtainDataSource 获取数据源。
- org.springframework.transaction.support.TransactionSynchronizationManager#getResource 获取 Resource,key 是 DataSource,具体是 HikariDataSource。如果是第一次进入事务,该事务未开启数据库连接,则返回空。
- txObject.setConnectionHolder(conHolder, false) 如果是第一次进入事务,则 conHolder 为空。
- org.springframework.jdbc.datasource.DataSourceTransactionManager#isExistingTransaction 判断释放已存在事务。
- 条件是
txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive()
。 - 如果是第一次进入事务,则为 false。
- 条件是
- org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction 如果当前已存在事务,处理逻辑。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#startTransaction 实际创建事务。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#newTransactionStatus 创建 DefaultTransactionStatus,执行
new DefaultTransactionStatus
。 - org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
- org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization 创建 TransactionStatus,准备 Synchronization。
- org.springframework.transaction.support.AbstractPlatformTransactionManager#newTransactionStatus 创建 DefaultTransactionStatus,执行
- 如果当前线程不存在事务,且事务传播规则是指定值,则调用 org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization 初始化事务同步 transaction synchronization。
- 传播规则指定值:PROPAGATION_NEVER,PROPAGATION_NOT_SUPPORTED,PROPAGATION_SUPPORTS。
- 创建 TransactionStatus,准备 Synchronization。
分支 DataSourceTransactionManager#doBegin
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
流程
- 如果 txObject 的实例变量 ConnectionHolder 为空(第一次进入事务),或已完成同步(
txObject.getConnectionHolder().isSynchronizedWithTransaction()
)。- org.springframework.jdbc.datasource.DataSourceTransactionManager#obtainDataSource 获取数据源。
- com.zaxxer.hikari.HikariDataSource#getConnection() 获取连接。当前使用的是 HikariDataSource。
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
填充 ConnectionHolder。
txObject.getConnectionHolder().setSynchronizedWithTransaction(true)
。标识资源已同步(resource,当前是指数据库连接)。- org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction 根据事务属性 definition 配置数据库连接的隔离级别。
- 为数据库连接配置其它属性,例如只读等等。当前事务事务,关闭自动提交。
txObject.getConnectionHolder().setTransactionActive(true);
。标识事务已激活。- 如果是新的 ConnectionHolder,则绑定 DataSource-ConnectionHolder 到当前线程,当前 DataSource 实际使用 HikariDataSource。调用 org.springframework.transaction.support.TransactionSynchronizationManager#bindResource。
分支 TransactionSynchronizationManager#bindResource
org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
流程
- org.springframework.transaction.support.TransactionSynchronizationUtils#unwrapResourceIfNecessary 获取 actualKey,如果是代理类,返回原始对象。
- 如果该 key 存在旧的值。
- 如果旧值是 ResourceHolder 且无效(ResourceHolder#isVoid 为 true),则忽略旧值。
- 否则抛出异常。
- 将新的值存储到 TransactionSynchronizationManager#resources 中。
分支 TransactionSynchronizationManager#getResource
- org.springframework.transaction.support.TransactionSynchronizationUtils#unwrapResourceIfNecessary 获取 actualKey,如果是代理类,返回原始对象。
- org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource 根据 key 获取当前线程绑定的资源。
- 根据 key 从 TransactionSynchronizationManager#resources 中查询当前线程绑定的资源。
- 如果值是 ResourceHolder 且无效(ResourceHolder#isVoid 为 true)则清除该对象,并返回 null。
- 否则返回找到的值。
分支 TransactionSynchronizationUtils#unwrapResourceIfNecessary
org.springframework.transaction.support.TransactionSynchronizationUtils#unwrapResourceIfNecessary
功能
获取 actualKey,如果是代理类,返回原始对象。
流程
- 特殊处理代理对象,如果 key 是 InfrastructureProxy 或 ScopedObject 实现类,则获取 target 原始对象。
- 否则直接返回原始对象。
分支 TransactionAspectSupport#prepareTransactionInfo
功能
封装事务相关信息为 TransactionInfo,并绑定到当前线程。
主流程
- 将关键事务信息封装为 TransactionInfo,执行
new TransactionInfo
。 - org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#newTransactionStatus 将 TransactionStatus 封装到 TransactionInfo 中。
- org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#bindToThread 绑定 TransactionInfo 到当前线程,并存储旧的 oldTransactionInfo,线程变量的持有者是 TransactionAspectSupport#transactionInfoHolder
关键类变量
|
|
|
|
|
|
|
|
绑定到当前线程的资源
- TransactionInfo
- org.springframework.transaction.interceptor.TransactionAspectSupport#transactionInfoHolder
private static final ThreadLocal<TransactionInfo> transactionInfoHolder = new NamedThreadLocal<>("Current aspect-driven transaction");
- 绑定时机 org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo
- 解绑或恢复挂起信息的时机 org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo
- 资源
- org.springframework.transaction.support.TransactionSynchronizationManager#resources
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
- 解绑或恢复挂起信息的时机 AbstractPlatformTransactionManager#cleanupAfterCompletion
- 同步
- org.springframework.transaction.support.TransactionSynchronizationManager#synchronizations
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
- 解绑或恢复挂起信息的时机 AbstractPlatformTransactionManager#cleanupAfterCompletion
- TransactionSynchronizationManager 中的事务标识信息
private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal<>("Actual transaction active");
- 解绑或恢复挂起信息的时机 AbstractPlatformTransactionManager#cleanupAfterCompletion
关键类描述
|
|
TransactionSynchronizationManager
org.springframework.transaction.support.TransactionSynchronizationManager
关键方法
TransactionSynchronizationManager#getResource
TransactionSynchronizationManager#doGetResource
TransactionSynchronizationManager#unbindResource
TransactionSynchronizationManager#doUnbindResource
事务判断
存在两种事务判断方法
- org.springframework.transaction.support.TransactionSynchronizationManager#isActualTransactionActive
- org.springframework.transaction.support.TransactionSynchronizationManager#isSynchronization
isActualTransactionActive
功能:检查当前是否存在真实的事务(物理事务)
isSynchronizationActive
功能:检查当前是否启用了事务同步
对比维度 | isActualTransactionActive | isSynchronizationActive |
---|---|---|
检查对象 | 检查真实事务是否存在 | 检查事务同步是否激活 |
返回true条件 | 存在物理事务 | 事务同步已初始化(可能没有真实事务) |
依赖关系 | 通常isSynchronizationActive为true时才会检查 | 不依赖事务是否存在 |
典型场景 | 判断是否在事务中执行 | 判断是否可以注册同步回调 |
物理事务是指在数据库层面实际开启的事务,具有ACID特性。当Spring说"存在物理事务"时,意味着:
- 数据库连接已设置非自动提交。
connection.setAutoCommit(false)
已被执行。 - 数据库已分配事务ID。数据库服务器内部已创建事务上下文(如MySQL的
tx_id
) - 资源已被绑定。JDBC Connection/Hibernate Session等资源已与当前线程绑定。
**** | 物理事务(Physical Transaction) | 逻辑事务(Logical Transaction) |
---|---|---|
****层级 | 数据库层面真实存在 | Spring抽象的事务概念 |
开启时机 | 仅当传播行为需要新事务时创建 | 所有@Transactional 方法都会进入逻辑事务 |
资源消耗 | 占用数据库连接和事务ID | 仅内存中的标记 |
示例场景 | PROPAGATION_REQUIRED 新建事务时 | PROPAGATION_SUPPORTS 无物理事务时 |
isSynchronizationActive 为 true,isActualTransactionActive 为 false 的场景
- 当方法使用 @Transactional(propagation = Propagation.SUPPORTS),且调用方无事务时。
- 手动初始化同步但未启动实际事务。
- 事务资源准备阶段,在事务管理器开始事务但尚未完成资源绑定时(短暂状态)。
- 其它。
事务关联
MyBatis 关联 Spring 事务
阶段1
org.apache.ibatis.executor.loader.ResultLoader#selectList
org.apache.ibatis.executor.loader.ResultLoader#newExecutor
environment.getTransactionFactory()
transactionFactory.newTransaction(
org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType)
org.apache.ibatis.executor.BaseExecutor#transaction 记录了 SpringManagedTransactionFactory 创建的事务,其中包含数据源。
阶段2
org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
org.apache.ibatis.executor.SimpleExecutor#doQuery
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
org.apache.ibatis.executor.BaseExecutor#getConnection
transaction.getConnection()
org.mybatis.spring.transaction.SpringManagedTransaction#getConnection
org.mybatis.spring.transaction.SpringManagedTransaction#openConnection
org.springframework.jdbc.datasource.DataSourceUtils#getConnection
org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection
TransactionSynchronizationManager.getResource(dataSource)