困难 · 高频 5/5
Spring 声明式事务在哪些场景会失效?
常见失效场景包括同类内部方法调用、方法非 public、异常被吞掉、异常类型不触发回滚、事务传播配置不当以及数据库引擎不支持事务。
简短答案
常见失效场景包括同类内部方法调用、方法非 public、异常被吞掉、异常类型不触发回滚、事务传播配置不当以及数据库引擎不支持事务。
详细解析
Spring 声明式事务基于 AOP 代理生效,所以调用必须经过代理对象。若在同一个类中直接调用事务方法,代理不会介入。
- 同类内部调用:绕过代理。
- 非 public 方法:默认不建议作为事务入口。
- 异常被 catch 后没有继续抛出:事务管理器认为执行成功。
- 默认只对 RuntimeException 和 Error 回滚。
- 异步线程、外部调用、传播行为配置错误也会带来误判。
面试回答模板
我会从代理机制讲起:声明式事务依赖 Spring AOP,必须经过代理对象才会开启事务。然后列举内部调用、异常处理、方法可见性、回滚异常类型、传播行为和数据库能力这些高频失效点。
易错点
- 只背结论,不解释原理和边界。
- 忽略真实生产环境中的容量、延迟、一致性和失败重试。
- 没有结合项目经验说明为什么这样设计。
常见追问
异常被 catch 后想回滚怎么办?
可以继续抛出异常,或显式调用 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()。