核心是让各环节感知并遵守同一事务边界。spring通过传播机制实现链式协同:默认required使方法加入外层事务;requires_new用于独立提交;线程切换需手动恢复上下文;跨服务需最终一致性或分布式事务方案。

在复杂业务链条中传递事务上下文,核心不是“把事务对象塞过去”,而是让各环节**感知并遵守同一事务边界**。Spring 的事务传播机制天然支持这种链式协同,关键在于合理配置传播行为、避免线程切换破坏上下文、并在跨线程/异步场景中主动恢复。
用对传播类型,让事务自然延展
多数业务方法应使用默认的 REQUIRED:
- 外层服务开启事务后,所有被它直接或间接调用的 @Transactional(propagation = Propagation.REQUIRED) 方法,自动加入同一事务;
- 即使跨 Service 类、跨模块调用(只要走 Spring 代理),事务上下文仍有效;
- 若某子流程必须独立提交(如记录日志、发通知),则改用 REQUIRES_NEW,原事务会被挂起,新事务完成后恢复执行。
警惕线程切换导致的上下文丢失
事务上下文绑定在线程上(通过 TransactionSynchronizationManager 的 ThreadLocal),一旦启用线程池、CompletableFuture 或手动新建线程,上下文即中断:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 不要在
new Thread(...).start()或executor.submit()中直接调用事务方法; - 若需异步执行且依赖事务状态(如读取当前只读标记),应在主线程中提前提取关键信息(如
isCurrentTransactionReadOnly()、getCurrentTransactionName()、资源绑定状态),再显式传入子任务; - 子任务内部可通过
TransactionSynchronizationManager.bindResource()和setCurrentTransactionReadOnly()手动恢复部分上下文(注意:仅限支持的资源类型,如DataSource)。
跨服务调用时,事务不传递,需换思路
HTTP、RPC 或消息队列调用天然跨进程,Spring 事务无法穿透:
- 不要试图把本地事务“传”给下游服务——这是分布式事务范畴;
- 推荐采用最终一致性方案:上游事务成功后,可靠投递事件(如 Kafka 消息),下游消费并执行自身事务;
- 若强一致要求高,可引入 Seata、Saga 或 TCC 模式,但需上下游共同改造,成本显著增加。
调试与验证事务是否真正串联
光看注解不够,要确认实际行为:
- 开启 Spring 日志:
logging.level.org.springframework.transaction=DEBUG,观察 “Creating new transaction” 或 “Participating in existing transaction” 提示; - 在关键方法入口打印
TransactionSynchronizationManager.getCurrentTransactionName(),相同名称说明在同一个事务中; - 故意在链路后半段抛出未捕获异常,验证前序 DB 操作是否回滚——这是最直接的验证方式。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










