Spring 事务传播机制源码深度解析

Spring 事务传播机制源码深度解析

Spring 事务传播机制是处理嵌套事务的核心逻辑,它定义了事务方法相互调用时事务的边界行为。本文将从源码层面深入剖析 Spring 事务传播机制的实现原理,通过关键类和方法解析揭示其内部工作机制。

一、传播机制的核心入口:getTransaction()

AbstractPlatformTransactionManager.getTransaction() 方法是传播机制的总入口,负责根据传播行为决定事务的创建、加入或挂起:

public final TransactionStatus getTransaction(TransactionDefinition definition) {
    // 1. 获取当前事务对象(数据源相关)
    Object transaction = doGetTransaction();
    
    // 2. 检查是否存在现有事务
    if (isExistingTransaction(transaction)) {
        // 存在事务:根据传播行为处理
        return handleExistingTransaction(definition, transaction);
    }
    
    // 3. 不存在事务:根据传播行为创建新事务
    return startTransaction(definition, transaction);
}

二、存在事务时的处理:handleExistingTransaction()

当检测到当前已存在事务时,Spring 会根据不同的传播行为采取不同策略:

private TransactionStatus handleExistingTransaction(
        TransactionDefinition definition, Object transaction) {
    
    // 1. NEVER:禁止在事务中运行
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
        throw new IllegalTransactionStateException(
            "Existing transaction found for transaction marked with propagation 'never'");
    }

    // 2. NOT_SUPPORTED:挂起当前事务,非事务执行
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
        Object suspendedResources = suspend(transaction);
        return prepareTransactionStatus(
            definition, null, false, false, suspendedResources);
    }

    // 3. REQUIRES_NEW:挂起当前事务,创建新事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
        SuspendedResourcesHolder suspendedResources = suspend(transaction);
        try {
            return startTransaction(definition, transaction, suspendedResources);
        } catch (RuntimeException | Error ex) {
            resumeAfterException(transaction, suspendedResources, ex);
            throw ex;
        }
    }

    // 4. NESTED:创建嵌套事务(保存点)
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
        if (!isNestedTransactionAllowed()) {
            throw new NestedTransactionNotSupportedException(...);
        }
        Object savepoint = createSavepoint();
        return prepareTransactionStatus(
            definition, transaction, false, true, savepoint);
    }

    // 5. 默认行为(REQUIRED, SUPPORTS, MANDATORY):加入当前事务
    return prepareTransactionStatus(
        definition, transaction, false, false);
}

三、关键传播行为源码解析

1. REQUIRES_NEW 传播行为

// 挂起当前事务
protected final SuspendedResourcesHolder suspend(Object transaction) {
    // 1. 解绑当前线程的事务资源
    List<TransactionSynchronization> suspendedSynchronizations = null;
    if (TransactionSynchronizationManager.isSynchronizationActive()) {
        suspendedSynchronizations = TransactionSynchronizationManager.getSynchronizations();
        TransactionSynchronizationManager.clearSynchronization();
    }
    
    // 2. 解绑事务资源(如数据库连接)
    Map<Object, Object> suspendedResources = new HashMap<>();
    for (Map.Entry<Object, Object> entry : resources.entrySet()) {
        Object key = entry.getKey();
        Object value = suspendResource(key);
        if (value != null) {
            suspendedResources.put(key, value);
        }
    }
    
    // 3. 返回挂起资源持有器
    return new SuspendedResourcesHolder(
        transaction, suspendedResources, suspendedSynchronizations);
}

// 创建新事务
private TransactionStatus startTransaction(
        TransactionDefinition definition, Object transaction,
        SuspendedResourcesHolder suspendedResources) {
    
    // 1. 开启新事务
    doBegin(transaction, definition);
    
    // 2. 准备事务状态(标记为新事务)
    return prepareTransactionStatus(
        definition, transaction, true, false, suspendedResources);
}

2. NESTED 传播行为

// 创建保存点
protected Object createSavepoint() {
    ConnectionHolder conHolder = (ConnectionHolder) 
        TransactionSynchronizationManager.getResource(dataSource);
    try {
        // 通过数据库连接创建保存点
        return conHolder.createSavepoint();
    } catch (SQLException ex) {
        throw new CannotCreateSavepointException("Could not create savepoint", ex);
    }
}

// 嵌套事务状态
public class NestedTransactionStatus extends DefaultTransactionStatus {
    private final Object savepoint;
    
    public NestedTransactionStatus(
            Object transaction, boolean newTransaction, Object savepoint) {
        super(transaction, newTransaction, false);
        this.savepoint = savepoint;
    }
    
    public boolean hasSavepoint() {
        return (this.savepoint != null);
    }
    
    public Object getSavepoint() {
        return this.savepoint;
    }
}

3. 嵌套事务回滚处理

protected void processRollback(DefaultTransactionStatus status, boolean unexpected) {
    try {
        if (status.hasSavepoint()) {
            // 嵌套事务:回滚到保存点
            status.rollbackToHeldSavepoint();
        } else if (status.isNewTransaction()) {
            // 新事务:完全回滚
            doRollback(status);
        } else if (status.hasTransaction()) {
            // 加入的事务:标记为回滚
            doSetRollbackOnly(status);
        }
    } finally {
        // 清理资源
        cleanupAfterCompletion(status);
    }
}

四、事务资源绑定机制

Spring 通过 TransactionSynchronizationManager 实现线程级事务资源绑定:

public abstract class TransactionSynchronizationManager {
    // 线程局部变量存储事务资源
    private static final ThreadLocal<Map<Object, Object>> resources =
        new NamedThreadLocal<>("Transactional resources");
    
    // 绑定资源到当前线程
    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 != null) {
            throw new IllegalStateException("Already value [" + oldValue + "] for key [" + key + "]");
        }
    }
    
    // 从当前线程解绑资源
    public static Object unbindResource(Object key) {
        Map<Object, Object> map = resources.get();
        if (map == null) {
            return null;
        }
        Object value = map.remove(key);
        if (map.isEmpty()) {
            resources.remove();
        }
        return value;
    }
}

五、传播行为执行流程图解

REQUIRED
SUPPORTS
MANDATORY
REQUIRES_NEW
NOT_SUPPORTED
NEVER
NESTED
REQUIRED
REQUIRES_NEW
NESTED
SUPPORTS
NOT_SUPPORTED
NEVER
MANDATORY
调用事务方法
当前是否存在事务?
处理传播行为
创建新事务
传播行为类型
加入当前事务
挂起当前事务
创建新事务
挂起当前事务
非事务执行
抛出异常
创建保存点
传播行为类型
创建新事务
非事务执行
抛出异常

六、传播机制与事务同步器

Spring 提供了 TransactionSynchronization 接口,允许在事务生命周期中插入自定义逻辑:

public interface TransactionSynchronization {
    // 事务挂起时调用
    void suspend();
    
    // 事务恢复时调用
    void resume();
    
    // 事务提交前调用(可访问事务资源)
    void beforeCommit(boolean readOnly);
    
    // 事务完成前调用(资源已关闭)
    void beforeCompletion();
    
    // 事务提交后调用
    void afterCommit();
    
    // 事务最终完成时调用
    void afterCompletion(int status);
}

同步器注册与触发

public abstract class AbstractPlatformTransactionManager {
    
    // 提交事务时触发同步器
    private void triggerBeforeCommit(DefaultTransactionStatus status) {
        if (status.isNewSynchronization()) {
            for (TransactionSynchronization synchronization : 
                 TransactionSynchronizationManager.getSynchronizations()) {
                synchronization.beforeCommit(status.isReadOnly());
            }
        }
    }
    
    // 事务完成后触发同步器
    private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
        if (status.isNewSynchronization()) {
            for (TransactionSynchronization synchronization : 
                 TransactionSynchronizationManager.getSynchronizations()) {
                synchronization.afterCompletion(completionStatus);
            }
        }
    }
}

七、传播机制在分布式事务中的扩展

Spring 通过 JtaTransactionManager 扩展传播机制支持分布式事务:

public class JtaTransactionManager extends AbstractPlatformTransactionManager {
    
    @Override
    protected Object doGetTransaction() {
        // 获取 JTA 事务
        Transaction tx = getTransactionManager().getTransaction();
        return new JtaTransactionObject(tx);
    }
    
    @Override
    protected boolean isExistingTransaction(Object transaction) {
        JtaTransactionObject txObject = (JtaTransactionObject) transaction;
        return (txObject.getTransaction() != null);
    }
    
    @Override
    protected void doBegin(Object transaction, TransactionDefinition definition) {
        // 开启 JTA 事务
        getTransactionManager().begin();
    }
    
    // 处理 REQUIRES_NEW 传播行为
    @Override
    protected Object doSuspend(Object transaction) {
        // 挂起 JTA 事务
        return getTransactionManager().suspend();
    }
    
    @Override
    protected void doResume(Object transaction, Object suspendedResources) {
        // 恢复 JTA 事务
        getTransactionManager().resume((Transaction) suspendedResources);
    }
}

八、最佳实践与性能优化

1. 传播行为选择建议

业务场景推荐传播行为说明
核心业务操作REQUIRED默认行为,加入或创建事务
独立日志记录REQUIRES_NEW确保日志记录独立提交
批量处理子项NESTED子项失败不影响整体
非关键操作NOT_SUPPORTED避免事务开销
强制事务环境MANDATORY确保在事务中执行

2. 性能优化策略

避免不必要的挂起操作

// 优化前:频繁挂起/恢复事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOperation(String message) {
    // 日志记录
}

// 优化后:批量处理减少挂起
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void batchLogOperations(List<String> messages) {
    for (String msg : messages) {
        logService.log(msg);
    }
}

合理使用只读事务

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public Report generateReport() {
    // 复杂查询操作
}

九、总结

Spring 事务传播机制的核心实现要点:

  1. 入口在 getTransaction():统一处理事务创建逻辑
  2. 传播行为决策树:通过 handleExistingTransaction() 实现不同传播策略
  3. 资源绑定机制:使用 TransactionSynchronizationManager 管理线程级资源
  4. 嵌套事务实现:基于数据库保存点(Savepoint)实现
  5. 分布式事务扩展:通过 JtaTransactionManager 支持 JTA

深入理解传播机制源码,有助于开发者:

  • 合理选择传播行为满足业务需求
  • 优化事务性能避免资源浪费
  • 排查复杂事务场景中的问题
  • 扩展自定义事务管理逻辑
  • 设计高效的事务处理方案

通过源码分析可见,Spring 事务传播机制的设计充分考虑了各种业务场景的需求,提供了灵活而强大的事务管理能力,是构建高可靠企业应用的重要基础。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值