当前位置: 首页 > ops >正文

Spring事务融入(REQUIRED)具体实现步骤解析

Spring事务融入(REQUIRED传播行为)是Spring事务管理中最核心的机制,下面我将深入剖析其具体实现步骤和关键代码逻辑。

1. 整体流程概览

事务融入(REQUIRED)的核心逻辑是:

  1. 检查当前线程是否存在事务

  2. 存在则融入(加入)该事务

  3. 不存在则创建新事务

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
}

执行流程

  1. methodA开始时创建新事务

  2. 调用methodB时检测到已有事务,直接融入

  3. 所有操作在同一个物理事务中执行

场景2:跨数据源事务融入

// 主数据源事务
@Transactional("primaryTransactionManager")
public void primaryOperation() {// 操作主库secondaryOperation(); // 调用次数据源操作
}// 次数据源事务
@Transactional("secondaryTransactionManager", propagation = Propagation.REQUIRED)
public void secondaryOperation() {// 操作从库
}

关键点

  • 不同TransactionManager无法真正融入同一事务

  • 实际会创建两个独立事务(需考虑分布式事务方案)

5. 实现注意事项

  1. 连接泄露防护

    • 通过ConnectionHolder跟踪连接状态

    • 事务结束时自动释放连接

  2. 嵌套调用处理

    • 通过事务状态对象跟踪嵌套深度

    • 只有最外层事务实际提交/回滚

  3. 同步回调管理

    • TransactionSynchronization注册回调

    • 保证资源清理顺序正确

  4. 异常处理机制

    • 默认只回滚RuntimeException

    • 可通过@Transactional配置自定义回滚规则

Spring通过这套精密的融入机制,实现了高效的事务管理,既保证了数据一致性,又提供了灵活的配置选项。

http://www.xdnf.cn/news/5234.html

相关文章:

  • 使用openlayers计算两个经纬度之间的距离 ,单位有米和千米
  • 区间 DP 详解
  • Java注解:深入探究理解与实践应用
  • SpringMVC-简介及入门
  • linux中常用的命令(三)
  • Java MCP 实战 --> AI玩转贪吃蛇
  • BUCK基本原理学习总结-20250509
  • JVM调优
  • python tkinter 实现 带界面(GUI)的RSA加密、签名
  • Linux终端展示效果优化:【whiptail】使用教程
  • 【目录】学习如何使用dify建设专业知识库
  • 【AI提示词】金字塔模型应用专家
  • 3.优惠券秒杀
  • c++类【高潮】
  • MySQL开篇
  • C++Primerplus编程练习 第八章
  • 生产级AI/ML特征存储平台:Feast全面使用指南 — Use Cases Third party integrations FAQ
  • java: Compilation failed: internal java compiler error 报错解决方案
  • 【Java学习日记32】:面向对象,类和对象
  • matlab介绍while函数
  • 计算机网络:怎么理解WIFI穿墙?
  • SSRF服务端请求伪造
  • 2025python学习笔记
  • 用tinyb210实现srsran小基站
  • 全国青少年信息素养大赛 Python编程挑战赛初赛 内部集训模拟试卷六及详细答案解析
  • 2025年保安员考试题库及答案
  • 电影感户外哑光人像自拍摄影Lr调色预设,手机滤镜PS+Lightroom预设下载!
  • Linux进程间信号
  • 【25软考网工】第六章(2)信息加密技术
  • 【金仓数据库征文】金仓数据库(KingbaseES)迁移与集群部署实战:从MySQL到KES的全流程解析