Spring Transaction 传播机制:事务同步管理器 ThreadLocal 绑定源码
标签:Spring | Transaction | 传播机制 | ThreadLocal
一、问题引入
java
@Service
public class OrderService {
@Transactional
public void createOrder() {
orderDao.insert(order); // 在事务 T1 中
// 以下调用的事务行为是什么?
inventoryService.deduct(); // REQUIRED → 加入 T1 还是新建?
logService.record(); // REQUIRES_NEW → 挂起 T1?
pointService.add(); // NESTED → 保存点?
}
}
Spring 事务的 7 种传播行为到底是如何实现的?事务的挂起和恢复在源码层面是怎么操作的?本文从 TransactionSynchronizationManager 的 ThreadLocal 绑定机制切入,深度解析 Spring 事务传播的核心源码。
二、TransactionSynchronizationManager:事务绑定的核心
2.1 ThreadLocal 存储结构
java
public abstract class TransactionSynchronizationManager {
// ★★★ 核心:ThreadLocal 存储每个线程的事务资源
// Key = DataSource, Value = ConnectionHolder(持有物理连接)
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
// 当前线程绑定的事务同步器
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
// 当前事务名
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
// 当前事务是否只读
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only flag");
// 当前事务隔离级别
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
// 当前事务是否活跃
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
}
设计要点:
- 使用
ThreadLocal<Map<DataSource, ConnectionHolder>>支持多数据源 ConnectionHolder包装物理连接,记录事务状态(是否开启、隔离级别)
2.2 绑定资源到线程
java
// 将 DataSource 的连接绑定到当前线程
public static void bindResource(Object key, Object value) {
Map<Object, Object> map = resources.get();
if (map == null) {
map = new HashMap<>();
resources.set(map);
}
Object oldValue = map.put(key, value);
if (oldValue instanceof ResourceHolder) {
((ResourceHolder) oldValue).unbound();
}
}
// 获取当前线程绑定的资源
public static Object getResource(Object key) {
Map<Object, Object> map = resources.get();
if (map != null) {
Object value = map.get(key);
if (value instanceof ResourceHolder
&& ((ResourceHolder) value).isVoid()) {
map.remove(key); // 清理失效资源
value = null;
}
if (value != null) {
return value;
}
}
// 尝试从 InheritableThreadLocal 获取(父子线程)
if (value == null) {
value = doGetResource(key, inheritableResources);
}
return value;
}
三、@Transactional 的拦截入口:TransactionInterceptor
3.1 拦截逻辑
java
public class TransactionInterceptor extends TransactionAspectSupport
implements MethodInterceptor {
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ?
AopUtils.getTargetClass(invocation.getThis()) : null);
// 调用父类的模板方法
return invokeWithinTransaction(invocation.getMethod(), targetClass,
invocation::proceed);
}
}
3.2 invokeWithinTransaction() 的模板方法
java
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 1. 获取事务属性(@Transactional 注解配置)
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ?
tas.getTransactionAttribute(method, targetClass) : null);
// 2. 获取事务管理器(PlatformTransactionManager)
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 3. 获取事务名称
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 4. 根据事务属性和管理器类型执行
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 标准声明式事务
// ★★★ 创建/加入事务(根据传播行为)
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// 执行业务方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// 回滚事务(根据 rollbackFor 配置)
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// 清理事务信息(恢复线程绑定)
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// ... CallbackPreferringPlatformTransactionManager 处理
}
四、createTransactionIfNecessary():传播行为的实现核心
4.1 事务获取流程
java
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 1. 创建事务状态
TransactionStatus status = tm.getTransaction(txAttr);
// 2. 封装为 TransactionInfo
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
// 3. ★★★ 绑定到当前线程
txInfo.bindToThread();
return txInfo;
}
4.2 AbstractPlatformTransactionManager.getTransaction():传播行为决策
java
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
// 1. 获取当前线程的事务对象
Object transaction = doGetTransaction();
// 2. 获取事务定义(传播行为、隔离级别等)
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
// 3. 检查当前是否已有事务
if (isExistingTransaction(transaction)) {
// ★★★ 当前已有事务,根据传播行为处理
return handleExistingTransaction(def, transaction, debugEnabled);
}
// 4. 当前没有事务
// 检查超时设置
if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
}
// 5. ★★★ 根据传播行为处理无事务场景
if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
} else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// ★★★ 挂起空事务(null),创建新事务
SuspendedResourcesHolder suspendedResources = suspend(null);
try {
return startTransaction(def, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
} else {
// PROPAGATION_SUPPORTS / NOT_SUPPORTED / NEVER
// 创建空事务(无实际事务)
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
}
}
4.3 handleExistingTransaction():已有事务时的传播处理
java
private TransactionStatus handleExistingTransaction(TransactionDefinition definition,
Object transaction, boolean debugEnabled) throws TransactionException {
// ========== PROPAGATION_NEVER:不允许有事务 ==========
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// ========== PROPAGATION_NOT_SUPPORTED:挂起当前事务 ==========
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
// ========== PROPAGATION_REQUIRES_NEW:挂起当前事务,创建新事务 ==========
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// ========== PROPAGATION_NESTED:创建保存点 ==========
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions");
}
if (useSavepointForNestedTransaction()) {
// 创建 JDBC 保存点
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
} else {
return startTransaction(definition, transaction, debugEnabled, null);
}
}
// ========== PROPAGATION_REQUIRED / SUPPORTS / MANDATORY:加入当前事务 ==========
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, transaction, false, newSynchronization,
debugEnabled, null);
}
五、事务的挂起(Suspend)与恢复(Resume)
5.1 suspend():挂起当前事务
java
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction)
throws TransactionException {
// 1. 检查是否有已同步的事务
if (TransactionSynchronizationManager.isSynchronizationActive()) {
// 获取所有同步器并解除绑定
List<TransactionSynchronization> suspendedSynchronizations =
TransactionSynchronizationManager.getSynchronizations();
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
synchronization.suspend();
}
// 2. 从 ThreadLocal 中清除事务信息
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);
// 3. 从 ThreadLocal 中解绑资源(DataSource → Connection)
Object suspendedResources = doSuspend(transaction);
// 4. 返回挂起的资源(后续恢复用)
return new SuspendedResourcesHolder(suspendedResources, suspendedSynchronizations,
name, readOnly, isolationLevel, wasActive);
}
// 没有活跃同步,但可能有资源
else if (transaction != null) {
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
return null;
}
5.2 doSuspend():解绑资源
java
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
// 从 ThreadLocal 中移除 DataSource → ConnectionHolder 的绑定
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(obtainDataSource());
}
5.3 resume():恢复挂起的事务
java
protected final void resume(@Nullable Object transaction,
@Nullable SuspendedResourcesHolder resourcesHolder) throws TransactionException {
if (resourcesHolder != null) {
Object suspendedResources = resourcesHolder.getSuspendedResources();
if (suspendedResources != null) {
// 重新绑定资源到 ThreadLocal
doResume(transaction, suspendedResources);
}
List<TransactionSynchronization> suspendedSynchronizations =
resourcesHolder.getSuspendedSynchronizations();
if (suspendedSynchronizations != null) {
// 恢复所有同步器
TransactionSynchronizationManager.setActualTransactionActive(
resourcesHolder.wasActive());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
resourcesHolder.getIsolationLevel());
TransactionSynchronizationManager.setCurrentTransactionReadOnly(
resourcesHolder.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(
resourcesHolder.getName());
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
synchronization.resume();
}
TransactionSynchronizationManager.initSynchronization();
}
}
}
六、7 种传播行为总结
| 传播行为 | 当前有事务 | 当前无事务 | 实现机制 |
|---|---|---|---|
REQUIRED |
加入 | 创建新事务 | 最常用,默认行为 |
SUPPORTS |
加入 | 无事务 | 查询方法可用 |
MANDATORY |
加入 | 抛异常 | 强制上层有事务 |
REQUIRES_NEW |
挂起当前,创建新 | 创建新事务 | 独立事务 |
NOT_SUPPORTED |
挂起当前,无事务 | 无事务 | 不需要事务的方法 |
NEVER |
抛异常 | 无事务 | 禁止事务 |
NESTED |
创建保存点 | 创建新事务 | JDBC Savepoint |
七、总结
| 组件 | 职责 |
|---|---|
TransactionSynchronizationManager |
ThreadLocal 绑定事务资源 |
TransactionInterceptor |
AOP 拦截 @Transactional 方法 |
AbstractPlatformTransactionManager |
传播行为决策 |
DataSourceTransactionManager |
JDBC 事务的具体实现 |
SuspendedResourcesHolder |
挂起事务的快照 |