跟着小马哥学系列之 Spring AOP(Spring 事务(源码分析)上)
学好路更宽,钱多少加班。 ——小马哥
简介
大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间《小马哥讲Spring AOP 编程思想》基础上形成的个人一些总结。希望能帮助各位小伙伴, 祝小伙伴早日学有所成。
@Transactional 注解
- 描述方法级别或类级别上的事务属性。
- 类级别注解应用所有默认方法以及子类。注意不会应用到祖先类;方法需要在本地重新声明,以便参与子类级别的注解。
- 这种注解类型通常直接与 Spring 的 RuleBasedTransactionAttribute 类相比较,事实上 A nnotationTransactionAttributeSource 将直接将数据转换为后一个类,因此 Spring 的事务支持代码不需要知道注解。如果没有与异常相关的规则,它将被当作 DefaultTransactionAttribute (回滚到RuntimeException 和 Error 上,但不回滚到检查异常上)。
属性 | 描述 |
---|---|
String value | 是 transactionManager 别名,表示事务管理器 |
String transactionManager | 是 value 别名,指定事务的限定符值。可以用于确定目标事务管理器,匹配特定 PlatformTransactionManager bean定义的限定符值(或bean名) |
Propagation propagation | 事务传播类型,默认值是 Propagation.REQUIRED |
Isolation isolation | 事务隔离级别,默认值是 Isolation.DEFAULT(如果你希望在参与具有不同隔离级别的现有事务时拒绝隔离级别声明,那么可以考虑将事务管理器上(AbstractPlatformTransactionManager)的 validateExistingTransaction 标志切换为 true) |
int timeout | 事务超时时间(单位:秒),默认值是 TransactionDefinition.TIMEOUT_DEFAULT |
boolean readOnly | 设置只读事务标志位,默认是 false |
Class<? extends Throwable>[] rollbackFor | 定义 0 或多个 Throwable 异常子类,用于回滚。默认事务回滚 RuntimeException 和 Error 但不是检查异常。优先于 rollbackForClassName 属性 |
String[] rollbackForClassName | 同 rollbackFor 属性同义,只不过指定异常类型的类名(可以不是全限定名) |
Class<? extends Throwable>[] noRollbackFor | 遇到指定异常不回滚 |
String[] noRollbackForClassName | 同 noRollbackFor 同义,只不过指定异常类型的类名(可以不是全限定名) |
TransactionDefinition
- 定义符合 Spring 的事务属性的接口。基于传播行为定义类似于 EJB CMT(容器管理事务) 属性;
- 请注意,除非启动实际的新事务,否则隔离级别和超时设置不会应用。因为只有PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 可能导致这种情况,所以在其他情况下指定这些设置通常没有意义。此外,请注意,并非所有事务管理器都支持这些高级功能,因此在给定非默认值时可能会抛出相应的异常;
- 只读标志适用于任何事务上下文,无论是由实际资源事务支持的,还是在资源级别上以非事务方式操作的。在后一种情况下,该标志将只应用于应用程序内的托管资源,比如 Hibernate Session;
字段 | 描述 |
---|---|
int PROPAGATION_REQUIRED = 0 | 支持当前事务,如果没有则新建一个事务 |
int PROPAGATION_SUPPORTS = 1 | 支持当前事务,如果不存在,则以非事务方式执行 |
int PROPAGATION_MANDATORY = 2 | 支持当前事务,如果不存在则会抛异常 |
int PROPAGATION_REQUIRES_NEW = 3 | 新建一个事务,挂起当前事务(如果有) |
int PROPAGATION_NOT_SUPPORTED = 4 | 不支持当前事务,如果存在则会挂起,它总是以非事务方式执行 |
int PROPAGATION_NEVER = 5 | 不支持当前事务,如果存在则会抛异常 |
int PROPAGATION_NESTED = 6 | 如果当前事务存在,则在嵌套事务中执行,否则行为类似于PROPAGATION_REQUIRED(通过数据库保护点(savepoint)来控制嵌套而不影响外部事务) |
int ISOLATION_DEFAULT = -1 | 使用底层数据源默认隔离级别(MySQL 默认隔离级别是 RR) |
int ISOLATION_READ_UNCOMMITTED = 1 | 对应 SQL 标准 READ_UNCOMMITTED 隔离级别。可能发生脏读、不可重复读和幻读。这个级别允许一个事务更改的行在该行的任何更改被提交之前被另一个事务读取(“脏读”)。如果回滚任何更改,第二个事务将获取无效行 |
int ISOLATION_READ_COMMITTED = 2 | 对应 SQL 标准 READ_COMMITTED 隔离级别。防止脏读,可能发生不可重复读和幻读。此级别仅禁止事务读取包含未提交更改的行 |
int ISOLATION_REPEATABLE_READ = 4 | 对应 SQL 标准 REPEATABLE_READ 隔离级别,防止脏读、不可重复读;可能发生幻读。这个级别禁止事务读取未提交更改的行,也禁止一个事务读取一行,另一个事务修改该行,第一个事务重新读取该行,第二次获得不同的值(“不可重复读取”) |
int ISOLATION_SERIALIZABLE = 8 | 对应 SQL 标准 SERIALIZABLE 隔离级别,防止脏读、不可重复读和幻读。这个级别包括 ISOLATION_REPEATABLE_READ 中的禁止,并进一步禁止以下情况:一个事务读取所有满足 where 条件的行,第二个事务插入一个满足 where 条件的行,第一个事务重新读取相同的条件。在第二次读取中检索附加的“幻”行 |
方法 | 描述 |
---|---|
getPropagationBehavior() | 返回传播行为 默认值 PROPAGATION_REQUIRED(0) |
getIsolation() | 返回隔离级别,默认值 ISOLATION_DEFAULT(-1) |
getTimeout() | 返回事务超时时间,默认值 TIMEOUT_DEFAULT(-1) |
isReadOnly() | 返回是否为只读事务,默认值是 false |
getName() | 返回此事务的名称。可以为空。如果适用的话(例如 WebLogic ),这将被用作事务监视器中显示的事务名称。对于 Spring 的声明性事务,公开的名称将是全限定的类名+"."+方法名(默认) |
withDefaults() | 使用默认值返回不可修改的 TransactionDefinition 对象 |
DefaultTransactionDefinition
TransactionDefinition 接口的默认实现,提供 bean 风格的配置和合理的默认值(PROPAGATION_REQUIRED、ISOLATION_DEFAULT、TIMEOUT_DEFAULT、readOnly=false)。TransactionTemplate 和 DefaultTransactionAttribute 的基类。
提供通过隔离级别(必须是 ISOLATION_ 开头,范围是 TransactionDefinition 里面的那些 ISOLATION_ 开头的常量字段名称)和传播行为(必须 PROPAGATION_开头,范围是 TransactionDefinition 里面的那些 PROPAGATION_ 开头的常量字段名称)名称设置对应的值,也可以直接设置隔离级别和传播行为(必须是 TransactionDefinition 对应的 int 值)以及超时时间的值
TransactionAttribute
该接口将 rollbackOn 属性添加到 TransactionDefinition。由于自定义 rollbackOn 仅适用于 AOP,因此它保存在与 AOP 相关的事务子包中。
方法 | 描述 |
---|---|
getQualifier() | 事务属性关联的限定符 |
roobackOn(Throwable) | 给定异常是否执行回滚 |
DefaultTransactionAttribute
Spring 的公共事务属性实现。默认情况下回滚 RuntimeException 和 Errior(排除 checked exceptions)
字段 | 描述 |
---|---|
String qualifier | 事务属性关联的限定符 |
String descriptor | 事务属性描述 |
都是一些简单的 getter/setter方法,主要介绍 rollbackOn 方法
@Override
public boolean rollbackOn(Throwable ex) {
// 回滚 RuntimeException 类型或者 Error 类型的异常
return (ex instanceof RuntimeException || ex instanceof Error);
}
RollbackRuleAttribute
确定发生异常(和任何子类)之后事务应该提交还是回滚的规则,可以有多个规则。
字段 | 描述 |
---|---|
String exceptionName | 异常名称 |
方法 | 描述 |
---|---|
getDepth(Throwable) | 返回匹配的深度(由实参异常类型向上父类递归匹配)。0 表示完全匹配,如果不匹配,返回 -1。否则返回最低匹配深度 |
public int getDepth(Throwable ex) {
return getDepth(ex.getClass(), 0);
}
private int getDepth(Class<?> exceptionClass, int depth) {
if (exceptionClass.getName().contains(this.exceptionName)) {
return depth;
}
// 一直递归到异常类型父类 Throwable 为终止条件
if (exceptionClass == Throwable.class) {
return -1;
}
// 使用异常父类类型进行递归匹配
return getDepth(exceptionClass.getSuperclass(), depth + 1);
}
NoRollbackRuleAttribute
RollbackAttribute 标记子类,与父类 RollbackRuleAttribute 行为相反(即发生异常不回滚)
RuleBasedTransactionAttribute
TransactionAttribute 实现通过应用若干回滚规则(正反两种)来判断给定的异常是否应该导致事务回滚。如果没有与异常相关的规则,它的行为就像DefaultTransactionAttribute(回滚运行时异常者 Error 类型的异常)。
字段 | 描述 |
---|---|
String PREFIX_ROLLBACK_RULE = “-” | 异常回滚规则字符串描述前缀 |
String PREFIX_ROLLBACK_RULE = “-” | 异常提交规则字符串描述前缀 |
List<RollbackRuleAttribute> roobackRules | 异常回滚/提交规则列表 |
@Override
public boolean rollbackOn(Throwable ex) {
if (logger.isTraceEnabled()) {
logger.trace("Applying rules to determine whether transaction should rollback on " + ex);
}
RollbackRuleAttribute winner = null;
int deepest = Integer.MAX_VALUE;
if (this.rollbackRules != null) {
for (RollbackRuleAttribute rule : this.rollbackRules) {
int depth = rule.getDepth(ex);
if (depth >= 0 && depth < deepest) {
deepest = depth;
winner = rule;
}
}
}
if (logger.isTraceEnabled()) {
logger.trace("Winning rollback rule is: " + winner);
}
// 如果没有找到规则使用默认规则(回滚 RuntimeException 类型或者 Error 类型的异常)
if (winner == null) {
logger.trace("No relevant rollback rule found: applying default rules");
return super.rollbackOn(ex);
}
// 如果匹配的规则是 NoRollbackRuleAttribute 则不回滚,否则回滚
return !(winner instanceof NoRollbackRuleAttribute);
}
Isolation
枚举,表示与 Transactional 注解一起使用的事务隔离级别,对应于 TransactionDefinition 接口。
枚举字段 | 对应 TransactionDefinition 字段 |
---|---|
DEFAULT | ISOLATION_DEFAULT |
READ_UNCOMMITTED | ISOLATION_READ_UNCOMMITTED |
READ_COMMITTED | ISOLATION_READ_COMMITTED |
REPEATABLE_READ | ISOLATION_REPEATABLE_READ |
SERIALIZABLE | ISOLATION_SERIALIZABLE |
Propagation
枚举,表示与 Transactional 注解一起使用的事务传播行为,对应于 TransactionDefinition 接口。
枚举字段 | 对应 TransactionDefinition 字段 |
---|---|
REQUIRED | PROPAGATION_REQUIRED |
SUPPORTS | PROPAGATION_SUPPORTS |
MANDTORY | PROPAGATION_MANDTORY |
REQUIRES_NEW | PROPAGATION_REQUIRES_NEW |
NOT_SUPPORTED | PROPAGATION_NOT_SUPPORTED |
NEVER | PROPAGATION_NEVER |
NESTED | PROPAGATION_NESTED |
SavepointManager
以通用方式通过特定的 API 编程方式管理事务保存点。通过 TransactionStatus 进行扩展,以暴露特定事务的保存点管理功能。
注意,保存点只能在活动事务中工作。只需使用这种程序化的保存点处理来满足高级需求;否则,最好使用带有 PROPAGATION_NESTED 的子事务。
方法 | 描述 |
---|---|
createSavepoint() | 创建一个新的保存点。你可以通过 rollbackToSavepoin t回滚到一个特定的保存点,并通过releaseSavepoint 显式地释放一个你不再需要的保存点。请注意,大多数事务管理器将在事务完成时自动释放保存点 |
rollbackToSavepoint(Object) | 回滚到给定的保存点。保存点之后不会自动释放。你可以显式地调用 releaseSavepoint(Object) 或者依赖于事务完成时的自动释放 |
releaseSavepoint(Object) | 显式释放给定的保存点。请注意,大多数事务管理器将在事务完成时自动释放保存点。如果最终会在事务完成时进行适当的资源清理,那么实现应该尽可能悄无声息地失败 |
TransactionExecution
事务当前状态的通用表示。作为 TransactionStatus 和 ReactiveTransaction 的基本接口。
方法 | 描述 |
---|---|
isNewTransaction() | 返回当前事务是否为新事务;否则会参与现有事务,或者可能不会首先在实际事务中运行 |
isRollbackOnly() | 返回事务是否被标记为仅回滚(应用程序或事务基础结构) |
setRollbackOnly() | 设置事务仅回滚。这指示事务管理器,事务的唯一可能结果可能是回滚,作为抛出异常的替代方法,该异常反过来会触发回滚 |
isCompleted() | 返回该事务是否已完成,即它是否已经提交或回滚 |
Flushable
Flushable 能把数据刷新到目的地。调用 flush 方法将缓冲区数据写入底层输出流。
方法 | 描述 |
---|---|
flush() | 刷缓冲区数据写入底层输出流 |
TransactionStatus
- 事务状态的表示。
- 编程式事务可以使用它来检索状态信息,并通过编程请求回滚(而不是抛出异常导致隐式回滚)。
- 包含 SavepointManager 接口,以提供对保存点管理工具的访问。请注意,保存点管理只有在底层事务管理器支持时才可用。
方法 | 描述 |
---|---|
flush() | 如果适用,将底层会话刷新到数据存储:例如,所有受影响的Hibernate/JPA会话。这实际上只是一个提示,如果底层事务管理器没有刷新概念,则可能是不操作的。刷新信号可能应用于主资源或事务同步,具体取决于底层资源 |
hasSavepoint() | 返回该事务是否在内部携带保存点,即是否已基于保存点创建为嵌套事务。此方法主要用于诊断目的,与 Transactionexecute#isNewTransaction() 一起使用。对于自定义保存点的编程处理,可以使用 SavepointManager 提供的操作 |
AbstractTransactionStatus
TransactionStatus 接口的抽象实现基类。预先实现本地回滚和已完成标志的处理,并委托给底层的 SavepointManager。还提供了在事务中保存保存点的选项。不假定任何特定的内部事务处理,例如底层事务对象,并且没有事务同步机制。
字段 | 描述 |
---|---|
boolean rollbackOnly | 事务回滚标志(默认 false) |
boolean completed | 事务是否完成标志(默认 false) |
Object savepoint | 保存点对象 |
方法 | 描述 |
---|---|
isLocalRollbackOnly() | 通过检查 TransactionStatu s确定回滚标志。如果应用程序在这个 TransactionStatus 对象上调用了setRollbackOnly,则只返回 true |
getSavepointManager() | 如果可能,返回底层事务的 SavepointManager |
releaseHeldSavepoint() | 释放事务持有的保存点(通过字段 SavepointManager) |
rollbackToHeldSavepoint() | 回滚事务持有的保存点,然后立即释放该保存点(通过字段 SavepointManager) |
createAndHoldSavepoint() | 创建一个保存点并保存到事务(通过字段 SavepointManager) |
set/getSavepoint() | 设置/获取事务的保存点 |
isGlobalRollbackOnly() | 模板方法,用于确定底层事务的全局回滚标志(如果有的话)。这个实现总是返回false |
DefaultTransactionStatus
TransactionStatus 接口默认实现,被用于 AbstractPlatformTransactionManager。基于底层事务对象的概念。保存 AbstractPlatformTransactionManager 内部需要的所有状态信息,包括由具体事务管理器实现确定的通用事务对象。支持将与保存点相关的方法委托给实现 SavepointManager 接口的事务对象。注意:这并不打算与其他 PlatformTransactionManager 实现一起使用,特别是不适用于测试环境中的模拟事务管理器。使用替代的 SimpleTransactionStatus 类或普通 TransactionStatus 接口的模拟。
字段 | 描述 |
---|---|
final Object transaction | 底层事务对象 |
final bollean newTransaction | 是否是新事务标志 |
final boolean newSynchronization | 新事务是否已同步标志 |
final readOnly | 是否是只读事务标志 |
final bollean debug() | 是否启用调试日志记录标志 |
final Object suspendedResources | 事务挂起的资源的持有者 |
方法 | 描述 |
---|---|
getTransaction() | 返回底层事务对象 |
hasTransaction() | 返回是否有实际激活的事务 |
isNewSynchronization() | 返回当前事务是否已打开同步新事务 |
isReadOnly/Debug() | 是否是只读事务/是否启用调试日志记录 |
isTransactionSavepointManager() | 底层事务对象是否实现了 SavepointManager 接口,从而是否支持保存点 |
getSuspendedResources() | 返回为此事务挂起的资源的持有者(如果有的话) |
SimpleTransactionStatus
TransactionStatus 简单实现。派生自 AbstractTransactionStatus 并添加显式的
newTransaction
标志。Spring 的任何预构建的 PlatformTransactionManager 实现都没有使用这个类。它主要作为自定义事务管理器实现的开始,以及测试事务代码的静态模拟(作为模拟 PlatformTransactionManage r的一部分,或作为传递到要测试的 TransactionCallback 中的参数)。
字段 | 描述 |
---|---|
final boolean newTransaction | 是否是新事务标志 |
事务管理器
ConnectionHandle
由 JDBC 连接句柄实现的简单接口。例如,由 JpaDialect 使用。
方法 | 描述 |
---|---|
getConnection() | 获取此句柄引用的 JDBC Connection |
releaseConnection(Connection) | 释放此句柄引用的 JDBC Connection |
SimpleConnectionHandle
ConnectionHandle接口的简单实现,包含一个给定的 JDBC Connection
字段 | 描述 |
---|---|
final Connection connection | Connection 对象,在构造的时候传入 |
ResourceHolder
由资源持有者实现的通用接口。允许 Spring 的事务基础结构在必要时内省和重置持有者。
方法 | 描述 |
---|---|
reset() | 重置此持有者的事务状态 |
unbound() | 通知此持有者它已从事务同步中解除绑定 |
isVoid() | 确定此持有者是否被认为是无效,即作为前一个线程的剩余部分 |
ResourceHolderSupport
便利的 ResourceHolder 接口实现基类。特色是支持参与事务的回滚。可以在一定的秒数或毫秒数之后过期,以确定事务超时。
字段 | 描述 |
---|---|
boolean synchronizedWithTransaction | 标记资源是否与事务同步(默认 false) |
boolean rollbackOnly | 标记资源事务是否回滚(默认 false) |
Date deadline | 超时截止日期 |
int referenceCount | 资源持有者引用计数 |
boolean isVoid | 标记持有者是否被认为是无效 |
方法 | 描述 |
---|---|
set/isSynchronizedWithTransaction() | 设置/获取资源为与事务同步 |
set/reset/isRollbackOnly() | 设置/重置/获取回滚标志 |
setTimeoutInSeconds/Millis() | 设置超时秒/毫秒 |
hasTimeout() | 是否关联超时时间 |
getDeadline() | 截止日期 |
getTimeToLiveInseconds/Millis() | 存活时间秒/毫秒 |
requested() | 将引用计数增加1,因为持有者已经被请求(即有人请求它所持有的资源) |
released() | 将引用计数减少1,因为持有者已经被释放(即有人释放了它所持有的资源) |
isOpen() | 返回是否仍有对该持有者的打开德引用 |
clear() | 清除此资源持有者的事务状态 |
ConnectionHolder
包装JDBC连接的资源持有者。DataSourceTransactionManager将这个类的实例绑定到特定数据源的线程。从基类继承回滚支持嵌套 JDBC 事务和引用计数功能。
字段 | 描述 |
---|---|
final String SAVEPOINT_NAME_PREFIX = “SAVEPOINT_” | 保护点名称前缀 |
ConnectionHandle connectionHandle | Connection 句柄内部包含一个 Connection |
Connection currentConnection | 当前 Connection |
boolean transactionActive | 事务是否已激活(默认 false) |
Boolean savepointsSupported | 是否支持保存点 |
itn savepointCounter | 保存点计数器,与 SAVEPOINT_NAME_PREFIX + savepointConter 构成保存点名称 |
构造器 | 描述 |
---|---|
ConnectionHolder(ConnectionHandle) | 为给定的 ConnectionHandle 创建一个新的ConnectionHolder |
ConnectionHolder(Connection) | 为给定的 JDBC 连接创建一个新的 ConnectionHolder,使用 SimpleConnectionHandle 包装它,假设没有正在进行的事务 |
ConnectionHolder(Connection, boolean) | 为给定的 JDBC 连接创建一个新的 ConnectionHolder,用SimpleConnectionHandle 包装它。同时设置给定的 Connection 是否包含在正在进行的事务中 |
方法 | 描述 |
---|---|
getConnectionHandler() | 获取 ConnectionHolder |
hasConnection() | 返回此持有者当前是否有 Connection |
set/isTransactionActive() | 设置/获取该持有人代表一个活动的、JDBC 管理的事务 |
setConnection(Connection) | 使用给定的 Connection 覆盖现有的 ConnectionHandle。如果给定 null,重置句柄。用于在挂起时释放连接(带一个空参数),并在恢复时设置一个新的连接 |
getConnection() | 返回此 ConnectionHolder 持有的当前连接。这将是相同的连接,直到 ConnectionHolder 调用释放,它将重置所持有的连接,按需获取一个新的连接 |
supportsSavepoints() | 返回是否支持 JDBC 3.0 保存点。在此 ConnectionHolder 的生命周期内缓存该标志 |
createSavepoint() | 为当前 Connection 新增一个新的 JDBC 3.0 保存点,使用生成的保存点名称在 Connection 中是唯一的 |
TransactionSynchronization
- 事务同步回调的接口。由 AbstractPlatformTransactionManager 支持。
- TransactionSynchronization 实现可以实现 Ordered 接口来影响它们的执行顺序。没有实现 Ordered 接口的同步被附加到同步链的末端。
- 由 Spring 本身执行的系统同步使用特定的顺序值,允许与它们的执行顺序进行细粒度的交互(如果必要的话)。
常量字段 | 描述 |
---|---|
int STATUS_COMMITTED = 0 | 提交情况下的完成状态 |
int STATUS_ROLLED_BACK = 1 | 回滚情况下的完成状态 |
int STATUS_UNKNOWN = 2 | 启发式混合完成或系统错误情况下的完成状态 |
方法 | 描述 |
---|---|
suspend() | 挂起同步。如果管理任何资源,则从 TransactionSynchronizationManager 解除资源绑定 |
resume() | 恢复同步。如果管理任何资源,应该将资源重新绑定到 TransactionSynchronizationManager |
flush() | 将底层 session 刷新到数据存储(如果适用的话):例如,Hibernate/JPA session |
befpreCommit(boolean) | 在事务提交之前调用(在 beforeCompletion 之前)。例如,可以刷新事务的 ORM session 到数据库。这个回调并不意味着事务将实际提交。在调用此方法之后,仍然可以执行回滚决策。这个回调是为了执行只有在提交仍有可能发生时才相关的工作,比如将 SQL 语句刷新到数据库。请注意,异常将传播到提交调用者,并导致事务回滚 |
beforeCompletion() | 在事务提交/回滚之前调用。可以在事务完成之前执行资源清理。此方法将在 beforeCommit 之后调用,即使beforeCommit抛出异常。这个回调允许在事务完成之前关闭任何结果的资源 |
afterCommit() | 事务提交后调用。可以在主事务成功提交后执行进一步的操作。例如,可以提交主事务成功提交后应该进行的进一步操作,如确认消息或电子邮件。注意:事务已经提交,但事务资源可能仍然是活动的和可访问的。因此,此时触发的任何数据访问代码仍将“参与“到原事务中,允许执行一些清理(不再有提交),除非它显式地声明需要在单独的事务中运行。因此,对从这里调用的任何事务操作使用 PROPAGATION_REQUIRES_NEW |
afterCompletion(int) | 事务提交/回滚后调用。可以在事务完成后执行资源清理。注意:事务将已经提交或回滚,但事务资源可能仍然是活动的和可访问的。因此,此时触发的任何数据访问代码仍将“参与“到原始事务中,允许执行一些清理(不再有提交),除非它显式地声明需要在单独的事务中运行。因此:对从这里调用的任何事务操作使用 PROPAGATION_REQUIRES_NEW |
TransactionSynchronizationManager
- 管理每个线程的资源和事务同步的中心委托。由资源管理代码使用,而不是由典型的应用程序代码使用。
- 每个键支持一个资源而不覆盖,即在为同一个键设置新资源之前,需要删除一个资源。如果同步是激活的,则支持事务同步列表。
- 资源管理代码应该通过 getResource 检查线程绑定的资源,例如 JDBC Connections 或 Hibernate Sessions。这类代码通常不应该将资源绑定到线程,因为这是事务管理器的职责。另一种选择是,如果事务同步是激活的,则在第一次使用时延迟绑定,以便执行跨任意数量资源的事务。
- 事务同步必须由事务管理器通过 initSynchronization() 和 clearSynchronization() 激活和停用。AbstractPlatformTransactionManager 自动支持此功能,因此所有标准的 Spring 事务管理器都支持此功能,例如 JtaTransactionManager 和org.springframework.jdbc.datasource.DataSourceTransactionManager
- 资源管理代码应该只在这个管理器是激活的时候注册同步,这可以通过 isSynchronizationActive() 检查,如果事务同步没有活动,则要么没有当前事务,要么事务管理器不支持事务同步。
- 例如,同步用于在 JTA 事务中总是返回相同的资源,例如 JDBC Connection 或 Hibernate Session ,分别针对任何给定的数据源或 SessionFactory
静态字段 | 描述 |
---|---|
ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>(“Transactional resources)” | 绑定到当前线程的所有资源 |
ThreadLocal<Set<TransactionSynchronizaiton>> synchronizations = new NamedThreadLocal<>(“Transactional synchronization)” | 绑定到当前线程的所有事务同步 |
ThreadLocal<String> currentTransactionName = new NamedThreadLocal<>(“Current transaction name”) | 绑定到当前线程的事务名 |
ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal<>(“Current transaction read-only status”) | 绑定到当前线程的是否是只读事务 |
ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal<>(“Current transaction isolation level”) | 绑定到当前线程事务的隔离级别 |
ThreadLocal<Boolean> currentTransactionActive = new NamedThreadLocal<>(“Actual transaction active”) | 绑定到当前线程的事务是否已激活 |
SuspendedResourcesHolder
AbstractPlatformTransactionManager 内部类,挂起资源的持有者。被内部挂起(suspend)和恢复(resume)使用。
字段 | 描述 |
---|---|
Object suspendedResources | 挂起的资源 |
List<TransactionSynchronization> suspendedSynchronizations | 挂起资源的事务同步 |
String name | 事务名称 |
boolean readOnly | 是否是只读事务 |
Integer isolationLevel | 事务隔离级别 |
boolea wasActive | 事务是否已激活 |
TransactionManager
Spring 事务管理器实现的标记接口,可以是传统的,也可以是响应式的。
PlatformTransactionManager
- Spring 事务设施中心接口。应用程序可以直接使用它,但它的主要含义不是 API:通常,应用程序通过 AOP 划分 TransactionTemplate 和声明性事务。
- 对于实现者,建议从提供的 AbstractPlatformTransactionManager 类派生,该类预先实现了已定义的传播行为,并负责事务同步处理。子类必须为底层事务的特定状态实现模板方法,例如:begin, suspend, resume, commit。
- 这个策略接口的默认实现是 JtaTransactionManager 和 org.springframework.jdbc.datasource.DataSourceTransactionManager,它可以作为其他事务策略的实现指南。
方法 | 描述 |
---|---|
getTransaction(TransactionDefinition) | 根据指定的传播行为返回当前激活的事务或者创建一个新事务。请注意,隔离级别或超时等参数只应用于新事务,因此在参与活动事务时将被忽略。此外,并非每个事务管理器都支持所有事务定义设置:当遇到不支持的设置时,适当的事务管理器实现应该抛出异常。上述规则的一个例外是只读标志,如果不支持显式只读模式,则应该忽略该标志。本质上,只读标志只是潜在优化的提示 |
commit(TransactionStatus) | 根据给定的事务的状态,提交事务。如果事务已被编程方式标记为回滚,则执行回滚。如果事务不是一个新的事务,可以省略参与事务的提交。如果以前的事务被挂起以创建新的事务,则在提交新事务后恢复以前的事务。请注意,当提交调用完成时,无论该事务是正常运行还是抛出异常,都必须完全完成并清除该事务。在这种情况下不应该期望回滚调用。如果此方法抛出一个 TransactionException 以外的异常,则提交之前的一些错误将导致提交尝试失败。例如,O/R Mapping工具可能试图在提交之前将更改刷新到数据库,结果导致DataAccessException导致事务失败。在这种情况下,原始异常将传播到此提交方法的调用者 |
rollback(TransactionStatus) | 对给定事务执行的回滚。如果该事务不是一个新的事务,只需将参与事务设置为 rollback-only。如果以前的事务被挂起以创建新的事务,则在回滚新事务后恢复以前的事务。如果提交引发异常,不要调用事务的回滚。当提交返回时,事务将已经完成并被清理,即使是在提交异常的情况下。因此,提交失败后的回滚调用将导致 IllegalTransactionStateException |
AbstractPlatformTransactionManager
- 实现 Spring 标准事务工作流的抽象基类,作为具体平台事务管理器(如JtaTransactionManager)的基础。这个基类提供了以下工作流处理:
- 确定是否存在现有事务
- 应用适当的传播行为
- 必要时挂起或恢复事务
- 在提交时检查回滚标志
- 在回滚(实际回滚或设置 rollback-only )上应用适当修改
- 触发注册的同步回调(如果事务同步是激活的)。
- 子类必须为事务的特定状态实现特定的模板方法,例如:开始、挂起、恢复、提交、回滚。其中最重要的是它们的抽象,必须由具体的实现来提供;对于其余部分,提供了默认值,因此重写是可选的。
- 事务同步是注册回调的通用机制,这些回调在事务完成时被调用。这主要用于 JDBC、Hibernate、JPA 等的数据访问支持类内部运行在 JTA 事务中:它们注册在事务中打开的资源,以便在事务完成时关闭,例如允许在事务中重用相同的Hibernate Session。同样的机制也可以用于应用程序中的自定义同步需求。
- 该类的状态是可序列化的,以允许序列化事务策略以及携带事务拦截器的代理。如果子类也希望使自己的状态可序列化,则由它们自己决定。在这种情况下,它们应该实现 java.io.Serializable 标记接口,如果需要恢复任何瞬态,可能还需要一个私有的 readObject() 方法(根据Java序列化规则)。
字段 | 描述 |
---|---|
int SYNCHRONIZATION_ALWAYS = 0 | 始终激活事务同步,即使是来自不存在后端事务的 PROPAGATION_SUPPORTS 的空事务 |
int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1 | 仅对实际事务激活事务同步,也就是说,不要对来自不存在后端事务的PROPAGATION_SUPPORTS的空事务激活事务同步 |
int SYNCHRONIZATION_NEVER = 2 | 从不激活事务同步,甚至对实际事务也不同步 |
Constants constant | 常量实例(上面那 3 个常量) |
int transactionSynchronization | 事务同步(默认值 SYNCHRONIZATION_ALWAYS ) |
int defaultTimeout | 默认超时时间(默认值 TransactionDefinition.TIMEOUT_DEFAULT) |
boolean nestedTransactionAllowed | 是否允许嵌套事务(默认 false) |
boolean validateExistingTransaction | 现有事务是否应在参与之前进行验证(默认 false) |
boolean globalRollbackOnParticipationFailure | 在参与的事务失败之后, 全局地将现有事务标记为回滚 (默认 true) |
boolean failEarlyOnGlobalRollbackOnly | 尽早失败,以防事务被全局标记为回滚(默认值 false) |
boolean rollbackOnCommitFailure | 设置 doCommit 调用失败时是否应该执行 doRollback(默认 false) |
方法 | 描述 |
---|---|
setValidateExistingTransaction(boolean) | 设置在参与现有事务之前是否应该验证它们。当参与现有事务时(例如,使用 PROPAGATION_REQUIRED 或 PROPAGATION_SUPPORTS 遇到现有事务),这个外部事务的特征甚至将应用于内部事务作用域。验证将检测内部事务定义上不兼容的隔离级别和只读设置,并通过抛出相应的异常拒绝参与。默认值是 false,宽大地忽略内部事务设置,简单地用外部事务的特征覆盖它们。将此标志切换为 true,以便执行严格的验证 |
setGlobalRollbackOnParticipationFailure(boolean) | 设置是否在参与事务失败后将现有事务全局标记为回滚。默认值为 true:如果参与的事务(例如使用 PROPAGATION_REQUIRED 或PROPAGATION_SUPPORTS 遇到现有事务)失败,该事务将全局标记为仅回滚。此类事务的唯一可能结果是回滚,事务发起者不能再提交事务。将其切换为 false,让事务发起者做出回滚决策。如果参与的事务出现异常而失败,调用者仍然可以决定在事务中继续使用不同的路径。但是,请注意,只有当所有参与的资源能够继续进行事务提交(即使在数据访问失败后)时,这才会起作用:例如,Hibernate会话通常不是这种情况;对于JDBC 插入/更新/删除操作序列也不是。注意:此标志仅适用于子事务的显式回滚尝试,通常由数据访问操作引发的异常引起(其中 TransactionInterceptor 将根据回滚规则触发 PlatformTransactionManager.rollback() 调用)。如果标志是关闭的,调用者可以处理异常并决定回滚,独立于子事务的回滚规则。然而,这个标志并不应用于 TransactionStatus 上的显式 setRollbackOnly 调用,它总是会导致最终的全局回滚(因为它可能不会在只回滚调用之后抛出异常)。处理子事务失败的推荐解决方案是“嵌套事务”,其中全局事务可以回滚到子事务开始时的保存点。PROPAGATION_NESTED 提供了这些语义;但是,它只在嵌套事务支持可用时才能工作。DataSourceTransactionManager 是这种情况,而 JtaTransactionManager 不是 |
setFailEarlyOnGlobalRollbackOnly(boolean) | 在事务被全局标记为回滚的情况下,设置是否尽早失败。默认值是 false,只会在最外面的事务边界上导致一个 UnexpectedRollbackException。在第一次检测到全局rollback-only标记时(甚至在内部事务边界内),将此标志切换到导致一个UnexpectedRollbackException。注意,从 Spring 2.0开始,全局只回滚标记的“早期失败”行为已经统一:所有事务管理器默认情况下只会在最外层事务边界上导致 UnexpectedRollbackException。例如,这允许在操作失败和事务永远不会完成之后继续单元测试。只有将此标志显式设置为 true 时,所有事务管理器才会早些时候失败 |
setRollbackOnCommitFailure(boolean) | 设置 doCommit 调用失败时是否应该执行 doRollback。这通常是不必要的,因此是要避免的,因为它可以潜在地用后续回滚异常覆盖提交异常。默认设置是 false |
doGetTransaction() | 返回当前事务状态的事务对象。返回的对象通常特定于具体的事务管理器实现,以可修改的方式携带相应的事务状态。这个对象将被传递给其他模板方法(例如 doBegin 和 doCommit),要么直接传递,要么作为 DefaultTransactionStatus 实例的一部分。返回的对象应该包含有关任何现有事务的信息,即在事务管理器上的当前 getTransaction 调用之前已经启动的事务。因此,doGetTransaction 实现通常会寻找现有的事务,并在返回的事务对象中存储相应的状态 |
isExistingTransation(Object) | 检查给定的事务对象是否表示一个现有的事务(即一个已经启动的事务)。结果将根据新事务的指定传播行为进行评估。现有事务可能会挂起(在 PROPAGATION_REQUIRES_NEW 的情况下),或者新事务可能参与现有事务(在 PROPAGATION_REQUIRED 的情况下)。默认实现返回 false,假设参与现有事务通常不受支持。当然也鼓励子类提供这种支持 |
useSavepointForNestedTransaction() | 返回是否为嵌套事务使用保存点。默认为 true,这将导致委托给 DefaultTransactionStatus 来创建和保存保存点。如果事务对象没有实现 SavepointManager 接口,将抛出 NestedTransactionNotSupportedException。否则,SavepointManager 将被要求创建一个新的保存点来界定嵌套事务的开始。子类可以覆盖此值以返回false,从而在已经存在的事务的上下文中进一步调用 doBegin。在这样的场景中,doBegin 实现需要相应地处理这个问题。例如,这适用于JTA |
doBegin(Object, TransactionDefinition) | 根据给定的事务定义,开始一个语义上新的事务。不需要关心传播行为的应用,因为这已经由这个抽象管理器处理。当事务管理器决定实际启动一个新事务时,将调用此方法。要么之前没有任何事务,要么之前的事务已挂起。一个特殊的场景是没有保存点的嵌套事务:如果 useSavepointForNestedTransaction() 返回 false,必要时将调用此方法来启动嵌套事务。在这样的上下文中,将会有一个激活的事务,此方法的实现必须检测到这一点并启动一个适当的嵌套事务 |
doSuspend(Object) | 挂起当前事务的资源。事务同步将已经挂起。默认实现抛出 TransactionSuspensionNotSupportedException,假设通常不支持事务挂起 |
doResume(Object, Object) | 恢复当前事务的资源。事务同步将在稍后恢复。默认实现抛出 TransactionSuspensionNotSupportedException,假设通常不支持事务挂起 |
shouldCommitOnGlobalRollbackOnly() | 返回是否以全局方式对标记为 rollback-only 的事务调用 doCommit。如果应用程序通过TransactionStatus 设置本地将事务为回滚,但仅通过事务协调器标记为回滚的事务本身设置为回滚,则不适用。默认值是 false:本地事务策略通常不会在事务本身中保留只回滚标记,因此它们不能将回滚事务作为事务提交的一部分来处理。因此,在这种情况下,AbstractPlatformTransactionManager将触发回滚,并在之后抛出一个UnexpectedRollbackException。如果具体事务管理器期望 doCommit 调用即使是回滚事务,可以重写当前方法返回 true,允许进行特殊处理。例如,这将是 JTA 的情况,其中 UserTransaction.commit 将检查只读标志本身并抛出一个相应的 RollbackException,该异常可能包括特定的原因(例如事务超时)。如果此方法返回 true,但 doCommit 实现没有抛出异常,则该事务管理器本身将抛出一个UnexpectedRollbackException。这不是典型的情况;它主要用于检查行为不当的 JTA 提供程序,这些 JTA 提供程序即使在调用代码没有请求回滚的情况下也会默默回滚 |
prepareForCommit(DefaultTransactionStatus) | 为提交做准备,在 beforeCommit 同步回调发生之前执行。请注意,异常将传播到提交调用者,并导致事务回滚 |
doCommit(DefaultTransactionStatus) | 实际执行给定事务的提交。实现不需要检查 new transaction 标志或 rollback-only 标志;之前已经处理过了。通常,直接提交的被执行事务对象包含传入的状态 |
doRollback(DefaultTransactionStatus) | 实际执行给定事务的回滚。实现不需要检查 new transaction 标志;之前已经处理过了。通常,直接回滚的被执行事务对象包含传入的状态 |
doSetRollbackOnly(DefaultTransactionStatus) | 设置给定事务回滚。只有在当前事务参与现有事务时才调用回滚。默认实现抛出一个 IllegalTransactionStateException,假设通常不支持参与现有事务。子类可以提供实现 |
registerAfterCompletionWithExistingTransaction(Object, List<TransactionSynchronization>) | 将给定的事务同步列表注册到现有事务。默认实现调用 afterCompletion 方法,传入 STATUS_UNKNOWN |
doCleanupAfterCompletion(Object) | 事务完成后清理资源。在执行 doCommit 和 doRollback 之后调用。默认空实现什么也不做。注意:实现的时候不应该抛出任何异常,而只是对错误发出警告 |
获取事务方法源码分析
getTransaction() 方法源码分析
此实现处理传播行为。委托 doGetTransaction, isExistingTransaction 和 doBegin
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 如果没有给出事务定义,则使用默认值
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 使用 doGetTransaction 模板方法获取事务对象
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
// 判断事务是否已存在(默认是 false)
if (isExistingTransaction(transaction)) {
// 已找到的事务 -> 检查传播行为以了解如何行为。构建不同行为的 DefaultTransactionStatus 实例
return handleExistingTransaction(def, transaction, debugEnabled);
}
// 检查超时时间
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 没有找到现有的事务->检查传播行为以找出如何继续。
// 没有找到事务,但是事务的传播行为是 PROPAGATION_MANDATORY 则报错
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
// 如果事务的传播行为是 PROPAGATION_REQUIRED 或者是 PROPAGATION_REQUIRES_NEW 或者是 PROPAGATION_NESTED
// 则创建事务
else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 挂起事务(不存在事务所以是 null)
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
}
try {
// 事务同步不是 SYNCHRONIZATION_NEVER 则是新同步
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建 DefaultTransactionStatus 实例
DefaultTransactionStatus status = newTransactionStatus(
def, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 开始一个具有语义的新事务
doBegin(transaction, def);
// 根据新事务同步初始化事务同步
prepareSynchronization(status, def);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// 剩余三种传播行为 PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
// 创建空事务:没有实际的事务,但可能存在同步。
if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + def);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
handleExistingTransaction() 方法源码分析
为现有事务创建一个 TransactionStatus
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// 发现事务的传播行为是 NEVER(不支持当前事务,如果存在则会抛异常) 就抛 IllegalTransactionStateException
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// 当事务的传播行为是 PROPAGATION_NOT_SUPPORTED 时,会打日志(如果日志级别是 debug)挂起当前事务等
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
// 挂起当前事务
Object suspendedResources = suspend(transaction);
// 如果所有传播行为都需要同步则是新同步否则则不是
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
// 构建 DefaultTransactionDefinition 实例,如果是新同步则进行新同步初始化并返回
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// 如果传播行为是 PROPAGATION_REQUIRES_NEW 挂起当前事务,新增新事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
// 挂起事务
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
// 事务同步不是 SYNCHRONIZATION_NEVER 既是新同步
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 获取 DefaultTransactionStatus 实例
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 根据给定的事务定义,开始一个语义上新的事务
doBegin(transaction, definition);
// 根据是否是新同步标志来初始化事务同步
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// 事务传播行为是 PROPAGATION_NESTED
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 如果不支持嵌套事务会报 NestedTransactionNotSupportedException 异常
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
// 如果支持嵌套事务使用保存点
if (useSavepointForNestedTransaction()) {
// 通过 TransactionStatus 实现的 SavepointManager API,
// 在现有 Spring 管理的事务中创建保存点。通常使用 JDBC 3.0 保存点。从不激活 Spring 同步。
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
// 创建保存点
status.createAndHoldSavepoint();
return status;
}
else {
// 嵌套事务通过嵌套的开始和提交/回滚调用。通常仅适用于JTA:
// 在存在预先存在的 JTA 事务的情况下,Spring 同步可能会被激活。
// 如果不支持保存点,则同上面的传播行为为 PROPAGATION_REQUIRES_NEW 处理
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
//假设事务传播行为是 PROPAGATION_SUPPORTS 或 PROPAGATION_REQUIRED。
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
// 在参与之前是否应该验证现有事务(默认是 false)
if (isValidateExistingTransaction()) {
// 如果不是默认隔离级别
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
// 获取当前线程绑定的隔离级别,如果没有设置或者与当前事务的隔离级别不一致则报错
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
// 不是只读事务
if (!definition.isReadOnly()) {
// 但是当前线程绑定的事务确是只读事务,则报错
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
// 事务同步不是 SYNCHRONIZATION_NEVER 既是新同步
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 构建 DefaultTransactionDefinition 实例,如果是新同步则进行新同步初始化并返回
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
suspend() 方法源码分析
挂起给定的事务。首先暂停事务同步,然后委托给 doSuspend 模板方法。
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
// 如果有事务同步则挂起,然后执行 doSuspend 模板方法,然后对 TransactionSynchronizationManager 进行重置
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
suspendedResources = doSuspend(transaction);
}
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
// 构造 SuspendResourceHolder 实例并返回
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
}
catch (RuntimeException | Error ex) {
// doSuspend 失败-原始事务仍然是激活,恢复挂起的同步
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}
else if (transaction != null) { // 事务处于激活状态,但同步没有激活。
// 调用 doSuspend 模板方法
Object suspendedResources = doSuspend(transaction);
// 返回 SuspendedResourceHolder 实例
return new SuspendedResourcesHolder(suspendedResources);
}
else {
// 事务和同步都没有激活。
return null;
}
}
doSuspendSynchronization() 方法源码分析
暂停所有当前同步并停用当前线程的事务同步
private List<TransactionSynchronization> doSuspendSynchronization() {
// 获取所有事物同步
List<TransactionSynchronization> suspendedSynchronizations =
TransactionSynchronizationManager.getSynchronizations();
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
// 挂起
synchronization.suspend();
}
// 清空
TransactionSynchronizationManager.clearSynchronization();
// 返回
return suspendedSynchronizations;
}
doResumeSynchronization() 方法源码分析
重新激活当前线程的事务同步并恢复所有给定的同步
private void doResumeSynchronization(List<TransactionSynchronization> suspendedSynchronizations) {
// 初始化同步
TransactionSynchronizationManager.initSynchronization();
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
// 恢复同步
synchronization.resume();
// 注册同步
TransactionSynchronizationManager.registerSynchronization(synchronization);
}
}
prepareTransactionStatus() 方法源码分析
为给定的参数创建一个新的TransactionStatus,并根据需要初始化事务同步
protected final DefaultTransactionStatus prepareTransactionStatus(TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
// 根据传参新增 DefaultTransaction 实例
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
// 根据是否是新同步标志来初始化事务同步
prepareSynchronization(status, definition);
return status;
}
newTransactionStatus() 方法源码分析
为给定的参数创建一个TransactionStatus实例
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
// 根据是新同步并且当前线程的事务同步不处于激活的状态来设置是新的事务同步
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
// 根据方法传参来创建 DefaultTransactionS
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
prepareSynchronization() 方法源码分析
适当初始化事务同步
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
// 如果为该事务打开了新的事务同步
if (status.isNewSynchronization()) {
// 根据传入的 DefaultTransactionStatus 对象中的事务对象是否为空来为当前线程绑定事务是否已激活
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
// 设置隔离级别,如果是默认的隔离级别则设置 null
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
// 设置只读事务标志
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
// 设置事务名称
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
// 初始化事务同步(为TransactionSynchronizationManager 对象中的 synchronizations 字段赋值一个 LinkedHashSet)
TransactionSynchronizationManager.initSynchronization();
}
}
回滚方法源码分析
rollback() 方法源码分析
参与现有事务回滚处理的实现。委托给 doRollback 和 doSetRollbackOnly
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
// 检查已完成状态,如果已完成则抛出 IllegalTransactionStateException
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 处理实际回滚
processRollback(defStatus, false);
}
processRollback() 方法源码分析
处理实际回滚。已完成标志已被检查
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
// 调用 triggerBeforeCompletion 方法(触发 TransactionSynchronization 中的 beforeCompletion 方法回调,上面已分析)
triggerBeforeCompletion(status);
// 如果有保存点,回滚到为事务保存的保存点,然后立即释放该保存点。
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
status.rollbackToHeldSavepoint();
}
// 如果是新事务调用 doRollback 模板方法
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
doRollback(status);
}
else {
// 参与在大的事务中
if (status.hasTransaction()) {
// 局部事务标记为回滚或者是全局地事务标记为回滚
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
// 调用 doSetRollbackOnly 模板方法
doSetRollbackOnly(status);
}
else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
}
else { // 没有事务打印日志
logger.debug("Should roll back transaction but cannot - no transaction available");
}
// 只有在我们被要求提前失败时,意外回滚才会产生影响
if (!isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = false;
}
}
}
catch (RuntimeException | Error ex) {
// 如果在回滚操作中发生了 RuntionException 或者是 Error 异常,则触发 TransactionSynchronization#afterCompletion 回调
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
// 正常 触发 TransactionSynchronization#afterCompletion 回调
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
// 如果我们有一个全局只回滚标记,则引发 UnexpectedRollbackException
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
}
finally {
// 完成后清理,必要时清除同步,并调用 doCleanupAfterCompletion 模板方法
cleanupAfterCompletion(status);
}
}
triggerBeforeCompletion() 方法源码分析
触发 TransactionSynchronization 中的 beforeCompletion 方法回调
protected final void triggerBeforeCompletion(DefaultTransactionStatus status) {
// 是新同步
if (status.isNewSynchronization()) {
if (status.isDebug()) {
logger.trace("Triggering beforeCompletion synchronization");
}
// 调用 TransactionSynchronization 中的 beforeCompletion 方法
TransactionSynchronizationUtils.triggerBeforeCompletion();
}
}
triggerAfterCompletion() 方法源码分析
触发 TransactionSynchronization 中的 afterCompletion 方法回调。
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
// 是新同步
if (status.isNewSynchronization()) {
// 获取所有同步
List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();
// 清除所有同步
TransactionSynchronizationManager.clearSynchronization();
if (!status.hasTransaction() || status.isNewTransaction()) {
if (status.isDebug()) {
logger.trace("Triggering afterCompletion synchronization");
}
// 调用 TransactionSynchronization 中的 afterCompletion 方法
invokeAfterCompletion(synchronizations, completionStatus);
}
else if (!synchronizations.isEmpty()) {
// 我们参与的现有事务,控制在这个 Spring 事务管理器的范围之外——>尝试向现有(JTA)事务注册一个 afterCompletion 回调。
registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
}
}
}
registerAfterCompletionWithExistingTransaction() 方法源码分析
将给定的事务同步列表注册到现有事务。当 Spring 事务管理器的控制以及所有 Spring 事务同步结束时调用,而事务尚未完成。这就是参与现有 JTA或 EJB CMT事务的例子。默认实现简单地立即调用afterCompletion方法,传入"STATUS_UNKNOWN"。如果没有机会确定外部事务的实际结果
protected void registerAfterCompletionWithExistingTransaction(
Object transaction, List<TransactionSynchronization> synchronizations) throws TransactionException {
logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +
"processing Spring after-completion callbacks immediately, with outcome status 'unknown'");
// 调用TransactionSynchronization 中的 afterCompletion 方法,不过完成状态是 STATUS_UNKNOWN
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
cleanupAfterCompletion() 方法源码分析
完成后进行清理,必要时清除同步,并调用 doCleanupAfterCompletion 模板方法
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
// 设置事务状态为已完成
status.setCompleted();
// 如果是新同步,清除当前线程的整个事务同步状态:已注册的同步以及各种事务特征。
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clear();
}
if (status.isNewTransaction()) {
doCleanupAfterCompletion(status.getTransaction());
}
// 如果挂起的资源不是 null,进行恢复
if (status.getSuspendedResources() != null) {
if (status.isDebug()) {
logger.debug("Resuming suspended transaction after completion of inner transaction");
}
Object transaction = (status.hasTransaction() ? status.getTransaction() : null);
resume(transaction, (SuspendedResourcesHolder) status.getSuspendedResources());
}
}
resume() 方法源码分析
恢复给定事务。首先委托给 doResume 模板方法,然后恢复事务同步
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder)
throws TransactionException {
// 挂起的资源句柄不为 null
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.suspendedResources;
if (suspendedResources != null) {
// 调用 doResume 模板方法
doResume(transaction, suspendedResources);
}
List<TransactionSynchronization> suspendedSynchronizations = resourcesHolder.suspendedSynchronizations;
if (suspendedSynchronizations != null) {
// 从挂起的资源恢复之前的状态(隔离级别、事务名、是不是只读事务、事务是不是激活)
TransactionSynchronizationManager.setActualTransactionActive(resourcesHolder.wasActive);
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(resourcesHolder.isolationLevel);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(resourcesHolder.readOnly);
TransactionSynchronizationManager.setCurrentTransactionName(resourcesHolder.name);
// 恢复事务同步
doResumeSynchronization(suspendedSynchronizations);
}
}
}
提交方法源码分析
commit() 方法源码分析
这个 commit 的实现处理参与现有事务和编程式回滚请求。委托给 isRollbackOnly、doCommit 和 rollback。
@Override
public final void commit(TransactionStatus status) throws TransactionException {
// 检查完成状态,如果已完成则报错
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
// 如果是局部回滚,则调用 processRollback 处理回滚
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
// 如果在全局回滚应该提交标记为 fasle(不应该提交) 并且全局回滚标记为 true
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
// 处理实际提交
processCommit(defStatus);
}
processCommit() 方法源码解析
处理实际提交。 回滚标志已被检查和应用
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
// beforeCompletion 调用标志
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
// 调用 prepareForCommit 模板方法
prepareForCommit(status);
// 触发 TransactionSynchronization#beforeCommit 回调
triggerBeforeCommit(status);
// 触发 TransactionSynchronization#beforeCompletion 回调
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
// 如果有保存点
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
unexpectedRollback = status.isGlobalRollbackOnly();
// 释放保存点
status.releaseHeldSavepoint();
}
// 如果是新事务
else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
unexpectedRollback = status.isGlobalRollbackOnly();
// 调用 doCommit 模板方法
doCommit(status);
}
// 如果是尽早失败全局回滚
else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
}
// 如果我们有一个全局回滚标记,但仍然没有从 commit 中获得相应的异常,抛出 UnexpectedRollbackException
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
catch (UnexpectedRollbackException ex) {
// 捕获 UnexpectedRollbackException 异常,调用 TransactionSynchronization#afterCompletion
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
catch (TransactionException ex) {
// 只能由 doCommit 引起,
// 返回 doCommit 调用失败时是否应该执行 doRollback。否则调用 TransactionSynchronization#afterCompletion
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
}
else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
}
catch (RuntimeException | Error ex) {
// 如果异常类型是 RuntimeException 或者 Error
if (!beforeCompletionInvoked) {
// beforeCompletion 回调没有调用,则调用 beforeCompletion 回调。
triggerBeforeCompletion(status);
}
// 提交发生异常,调用 doRollback 正确处理回滚异常。
doRollbackOnCommitException(status, ex);
throw ex;
}
// 在 commit 后触发回调,并将在那里抛出的异常传播给调用方,但事务仍被视为已提交。
try {
// 触发 TransactionSynchronization#afterCommit 回调
triggerAfterCommit(status);
}
finally {
// 触发 TransactionSynchronization#afterCompletion 回调
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
// 设置事务完成状态,必要时清除同步,并调用 doCleanupAfterCompletion,如果有挂起的资源,进行恢复
cleanupAfterCompletion(status);
}
}
triggerBeforeCommit() 方法源码分析
触发 TransactionSynchronization#beforeCommit 回调。
protected final void triggerBeforeCommit(DefaultTransactionStatus status) {
// 是新同步则调用 TransactionSynchronization#beforeCommit 回调方法
if (status.isNewSynchronization()) {
if (status.isDebug()) {
logger.trace("Triggering beforeCommit synchronization");
}
TransactionSynchronizationUtils.triggerBeforeCommit(status.isReadOnly());
}
}
doRollabckCommitException() 方法源码分析
调用 doRollback ,正确处理回滚异常。
private void doRollbackOnCommitException(DefaultTransactionStatus status, Throwable ex) throws TransactionException {
try {
// 如果是新事务调用 doRollbck 模板方法
if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback after commit exception", ex);
}
doRollback(status);
}
// 如果有事务并且全局回滚被标记,则调用 doSetRollbackOnly 模板方法
else if (status.hasTransaction() && isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Marking existing transaction as rollback-only after commit exception", ex);
}
doSetRollbackOnly(status);
}
}
catch (RuntimeException | Error rbex) {
// 如果发生了 RuntimeException 或者 Error 异常,则触发 afterCompletion 回调(同步状态是 STATUS_UNKNOWN)
logger.error("Commit exception overridden by rollback exception", ex);
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw rbex;
}
// 正常触发 afterCompletion 回调(同步状态是 STATUS_ROLLED_BACK)
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
}