Spring调用this导致事务失效的三种解决方案
作者:五阿哥永琪
在 Spring 事务管理 中,如果你在同一个类的方法内部使用 this.xxx() 调用另一个带 @Transactional 的方法,事务很可能会失效,这不是玄学,而是代理机制在背后打盹了,本文就给大家介绍如何解决this调用导致事务失效问题,需要的朋友可以参考下
一、为什么this调用会导致事务失效?
Spring 的声明式事务基于 AOP 代理 实现:
- Spring 为你的 Bean 创建一个 代理对象
- 事务逻辑在代理对象中织入
- 只有 通过代理对象调用方法 才会触发事务
失效场景
@Service
public class OrderService {
public void createOrder() {
// 直接调用
this.saveOrder(); // ❌ 不经过代理
}
@Transactional
public void saveOrder() {
// 数据库操作
}
}
调用路径:
createOrder() → this.saveOrder()
这里没有经过 Spring 代理 → 事务不会生效。
二、如何保证事务生效?
方案一:通过 Spring 代理对象调用(推荐⭐⭐⭐⭐⭐)
方法1:注入自身代理
@Service
public class OrderService {
@Autowired
private OrderService orderService; // 注入代理对象
public void createOrder() {
orderService.saveOrder(); // ✅ 通过代理调用
}
@Transactional
public void saveOrder() {
}
}
原理:Spring 注入的是代理对象,而不是原始对象。
方法2:使用 AopContext 获取代理(需开启暴露代理)
① 开启配置
@EnableAspectJAutoProxy(exposeProxy = true)
② 调用方式
public void createOrder() {
((OrderService) AopContext.currentProxy()).saveOrder();
}
适合不想注入自身的场景。
方案二:拆分到不同 Service(最佳实践⭐⭐⭐⭐⭐)
这是企业项目最推荐的结构设计。
@Service
public class OrderService {
@Autowired
private OrderTxService orderTxService;
public void createOrder() {
orderTxService.saveOrder();
}
}
@Service
public class OrderTxService {
@Transactional
public void saveOrder() {
}
}
✔ 更清晰
✔ 职责单一
✔ 更利于维护 & 扩展
这是大型系统常见架构方式。
方案三:使用编程式事务(不常用)
@Autowired
private TransactionTemplate transactionTemplate;
public void createOrder() {
transactionTemplate.execute(status -> {
saveOrder();
return null;
});
}
适用于:
- 需要精细控制事务
- 复杂业务流程
但日常开发不推荐优先使用。
以上就是Spring调用this导致事务失效的三种解决方案的详细内容,更多关于Spring调用this导致事务失效的资料请关注脚本之家其它相关文章!
