@Transactional 同类内部调用失效 + 两种自代理解决方案
问题根源
Spring AOP 事务靠代理对象 生效;同类 this.xxx() 是原对象直接调用,不走代理 → 事务注解失效。
@Service
public class OrderService {
@Transactional
public void createOrder() {}
// ❌ 内部调用,事务不生效
public void test() {
this.createOrder();
}
}
方案 1:注入自身 Bean(最简单,推荐)
写法:本类注入自己
@Service
public class OrderService {
// 自注入代理对象
@Autowired
private OrderService self;
@Transactional
public void createOrder() {
// 新增订单,事务生效
}
public void test() {
// ✅ 使用代理对象调用,触发AOP事务
self.createOrder();
}
}
Spring 循环依赖三级缓存天然支持自己注入自己,不会报错。
方案 2:AopContext.currentProxy () 获取当前代理
第一步:开启暴露代理
<!-- xml配置 -->
<aop:aspectj-autoproxy expose-proxy="true"/>
// java配置
@EnableAspectJAutoProxy(exposeProxy = true)
第二步:代码获取代理
@Service
public class OrderService {
@Transactional
public void createOrder(){}
public void test() {
// ✅ 拿到代理对象
OrderService proxy = (OrderService) AopContext.currentProxy();
proxy.createOrder();
}
}
总结选型
- 优先:自注入 self,代码整洁、可读性好、无配置依赖;
- 备选:AopContext ,不想多一个成员变量时使用,必须开启
exposeProxy=true。
拓展:构造注入自引用(Spring4.3+)
private final OrderService self;
public OrderService(OrderService self){
this.self = self;
}