Spring Transaction 传播机制


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 挂起事务的快照

相关推荐
闪电悠米1 小时前
黑马点评-分布式锁-03_lua_atomic_unlock
java·数据库·分布式·缓存·oracle·wpf·lua
多工坊1 小时前
The content of elements must consist of well-formed character data or markup.
java
linmoo19861 小时前
Java踩坑系列之二:ThreadLocal内存泄漏
java·内存泄漏·threadlocal·踩坑
27669582921 小时前
拼多多m端/小程序 encrypt_info
java·小程序·apache·encrypt_info·encrypt_info解密·拼多多小程序·拼多多m端
码不停蹄的玄黓1 小时前
Java 应用 CPU 过高排查全流程
java·开发语言·python
许彰午1 小时前
11_Java集合框架概述
java·windows·python
小谢小哥1 小时前
64-依赖冲突解决详解
java·后端·架构