← 返回文章

Java

Spring 事务失效:从代理边界开始排查

从 AOP 代理边界出发,梳理自调用、异常处理和传播行为如何影响事务是否真正生效。

描绘 Service、AOP Proxy 和数据库调用关系的暖橙色封面图
本文目录

事务问题往往不是注解写错,而是我们对“谁负责拦截这次调用”理解得不够清楚。下面用代理边界作为起点,建立一套更可靠的排查顺序。

事务代理调用流程

为什么事务会悄悄失效?

@Transactional 不是方法本身的能力,而是 Spring 在调用进入代理时附加的一层行为。只有调用经过代理,事务管理器才能在进入目标方法前开启事务,并在方法结束后决定提交还是回滚。

自调用绕开代理

同一个类里的 this.someTransactionalMethod() 属于普通 Java 方法调用,它不会回到 Spring 创建的代理对象。因此,标了事务的方法可能像普通方法一样执行。

优先把需要独立事务边界的操作拆到另一个服务中;若必须保留在同一类,也要明确通过代理入口调用,而不是把实现细节隐藏在一次自调用里。

异常被吞掉

事务默认依赖异常信号决定回滚。如果捕获异常后只记录日志并继续返回成功结果,代理看到的就是一次正常完成的调用。需要恢复时,应重新抛出可回滚的异常,或明确标记当前事务为 rollback-only。

一套更快的排查顺序

  1. 确认调用是否从 Spring 管理的 Bean 进入;
  2. 确认目标方法是否被代理规则覆盖;
  3. 检查异常是否被转换或吞掉;
  4. 最后再看传播行为、只读配置与数据库引擎能力。

这套顺序把“事务注解为什么没生效”的问题,收敛为可观察的调用边界,而不是盲目调整配置。