Spring事务融入(REQUIRED)具体实现步骤解析
Spring事务融入(REQUIRED传播行为)是Spring事务管理中最核心的机制,下面我将深入剖析其具体实现步骤和关键代码逻辑。
1. 整体流程概览
事务融入(REQUIRED)的核心逻辑是:
-
检查当前线程是否存在事务
-
存在则融入(加入)该事务
-
不存在则创建新事务
2. 详细实现步骤
步骤1:事务获取入口
从@Transactional
注解或编程式事务调用开始,最终会进入PlatformTransactionManager
的实现类:
// AbstractPlatformTransactionManager.java
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) {// 获取或创建事务对象Object transaction = doGetTransaction();// 检查是否存在事务if (isExistingTransaction(transaction)) {// 存在事务则处理融入逻辑return handleExistingTransaction(def, transaction, debugEnabled);}// 不存在事务则创建新事务return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
步骤2:判断是否存在事务
以DataSourceTransactionManager为例:
// DataSourceTransactionManager.java
@Override
protected boolean isExistingTransaction(Object transaction) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;// 关键判断:连接持有者不为null且连接已开启事务return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
步骤3:处理已存在事务(融入核心)
// AbstractPlatformTransactionManager.java
private TransactionStatus handleExistingTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled) {// 1. 处理NEVER传播行为if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {throw new IllegalTransactionStateException(...);}// 2. 处理NOT_SUPPORTED传播行为(挂起现有事务)if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {Object suspendedResources = suspend(transaction);return prepareTransactionStatus(...);}// 3. 处理REQUIRES_NEW传播行为(挂起并新建)if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {SuspendedResourcesHolder suspendedResources = suspend(transaction);return startTransaction(definition, transaction, debugEnabled, suspendedResources);}// 4. 处理NESTED传播行为(创建保存点)if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {if (!isNestedTransactionAllowed()) {throw new NestedTransactionNotSupportedException(...);}Object savepoint = createSavepoint(transaction);return prepareTransactionStatus(...);}// 5. 默认处理REQUIRED/SUPPORTS/MANDATORY(融入现有事务)if (debugEnabled) {logger.debug("Participating in existing transaction");}// 关键点:设置"新事务"标志为false,表示融入现有事务return prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
}
步骤4:准备事务状态(融入关键)
// AbstractPlatformTransactionManager.java
protected final DefaultTransactionStatus prepareTransactionStatus(TransactionDefinition definition, Object transaction, boolean newTransaction, boolean newSynchronization,boolean debug, @Nullable Object suspendedResources) {// 创建事务状态对象DefaultTransactionStatus status = newTransactionStatus(definition, transaction, newTransaction, newSynchronization,debug, suspendedResources);// 初始化事务同步(重要!)prepareSynchronization(status, definition);return status;
}
步骤5:事务同步准备
// AbstractPlatformTransactionManager.java
protected void prepareSynchronization(DefaultTransactionStatus status,TransactionDefinition definition) {if (status.isNewSynchronization()) {// 初始化新事务的同步器TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel());TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());// 初始化同步回调列表TransactionSynchronizationManager.initSynchronizations();}
}
3. 关键实现技术
3.1 线程绑定机制
Spring通过TransactionSynchronizationManager
维护线程绑定资源:
// TransactionSynchronizationManager.java
private static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");public static void bindResource(Object key, Object value) {Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);Map<Object, Object> map = resources.get();if (map == null) {map = new HashMap<>();resources.set(map);}Object oldValue = map.put(actualKey, value);// 检查是否重复绑定if (oldValue != null) {throw new IllegalStateException(...);}
}
3.2 连接资源管理
DataSourceTransactionManager对Connection的管理:
// DataSourceTransactionManager.java
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;Connection con = null;try {// 获取或创建连接if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {Connection newCon = obtainDataSource().getConnection();txObject.setConnectionHolder(new ConnectionHolder(newCon), true);}// 设置事务属性con = txObject.getConnectionHolder().getConnection();Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);// 设置自动提交为falseif (con.getAutoCommit()) {con.setAutoCommit(false);}// 绑定到当前线程bindResource(obtainDataSource(), txObject.getConnectionHolder());}catch (Throwable ex) {// 异常处理...}
}
4. 事务融入的典型场景
场景1:ServiceA调用ServiceB
// ServiceA
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {// 操作1serviceB.methodB(); // 融入同一事务// 操作2
}// ServiceB
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {// 操作3
}
执行流程:
-
methodA开始时创建新事务
-
调用methodB时检测到已有事务,直接融入
-
所有操作在同一个物理事务中执行
场景2:跨数据源事务融入
// 主数据源事务
@Transactional("primaryTransactionManager")
public void primaryOperation() {// 操作主库secondaryOperation(); // 调用次数据源操作
}// 次数据源事务
@Transactional("secondaryTransactionManager", propagation = Propagation.REQUIRED)
public void secondaryOperation() {// 操作从库
}
关键点:
-
不同TransactionManager无法真正融入同一事务
-
实际会创建两个独立事务(需考虑分布式事务方案)
5. 实现注意事项
-
连接泄露防护:
-
通过ConnectionHolder跟踪连接状态
-
事务结束时自动释放连接
-
-
嵌套调用处理:
-
通过事务状态对象跟踪嵌套深度
-
只有最外层事务实际提交/回滚
-
-
同步回调管理:
-
TransactionSynchronization注册回调
-
保证资源清理顺序正确
-
-
异常处理机制:
-
默认只回滚RuntimeException
-
可通过@Transactional配置自定义回滚规则
-
Spring通过这套精密的融入机制,实现了高效的事务管理,既保证了数据一致性,又提供了灵活的配置选项。