03.3 传播行为与隔离级别
本章深入 7 种传播行为的源码实现、事务的挂起与恢复机制、以及各传播行为是否新建物理连接的底层分析。
1. 事务的挂起与恢复(suspend / resume)
挂起的核心代码
java
// AbstractPlatformTransactionManager.suspend()
@Nullable
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction)
throws TransactionException {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 1. 触发所有同步器的 suspend 回调
List<TransactionSynchronization> suspendedSynchronizations =
TransactionSynchronizationManager.getSynchronizations();
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
synchronization.suspend();
}
// 2. 清空当前线程的同步器
TransactionSynchronizationManager.clearSynchronization();
}
// 3. 解绑并保存资源(ConnectionHolder 等)
Map<Object, Object> suspendedResources = null;
if (transaction != null) {
suspendedResources = TransactionSynchronizationManager.getResourceMap().isEmpty() ?
null : new HashMap<>(TransactionSynchronizationManager.getResourceMap());
// 解绑所有资源
// 这样后续的 DAO 操作就拿不到旧连接了
}
// 4. 保存事务名称/只读/隔离级别/活跃状态
String suspendedName = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
Boolean suspendedReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(null);
Integer suspendedIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
Boolean suspendedActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
// 5. 将所有保存的信息包装返回
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations,
suspendedName, suspendedReadOnly, suspendedIsolationLevel, suspendedActive);
}2. Propagation 行为源码级对比
| 传播行为 | handleExistingTransaction 处理 | isNewTransaction | 底层行为 | 是否新建连接 |
|---|---|---|---|---|
| REQUIRED | 直接返回,不做操作(加入) | false | 共享同一 Connection | ❌ |
| REQUIRES_NEW | suspend() → 解绑旧连接 → doBegin() 获取新连接 | true | 使用全新 Connection | ✅ |
| NESTED | createAndHoldSavepoint() → 设置 JDBC 保存点 | false | 同一 Connection 不同保存点 | ❌ |
| NOT_SUPPORTED | suspend() → 非事务运行 | false | 挂起事务,无事务运行 | ❌(暂不绑定) |
| SUPPORTS | 直接返回,不做操作 | false | 同 REQUIRED 但无事务 | ❌ |
| MANDATORY | 直接返回,不做操作 | false | 同 REQUIRED | ❌ |
| NEVER | 抛异常 | — | 拒绝事务上下文 | — |
核心面试题
- REQUIRES_NEW 在同一个事务管理器下真的会新建物理连接吗?挂起和恢复的机制?
- NESTED 传播行为底层如何实现?如何做到只回滚部分操作?
- Spring 事务传播行为执行流程对比:REQUIRED、REQUIRES_NEW、NESTED 的区别?
← 返回 **返回 事务管理索引**