在Springboot中如果一个AService中a/b/c 方法,那么 b、c 做的传播行为配置,都不会起作用,也就是说b、c都会跟 a 共用一个事务都采用@Transactional(propagation = Propagation.REQUIRED),这个注解就会失效;
除非b、c在其他不同的 service,那样才能使它们自己的配置生效
- 原因
那为什么会出现这种情况呢?
事务是用代理对象来控制的,如果在 a 里面调用的是同一个 service 的 b、c方法,相当于把 b、c 的代码复制、粘贴过来了,直接调用的本类的方法,而不是通过AOP代理增强调用,也就是跳过了代理
解决
使用代理对象调用b、c方法,即可解决
- 引入依赖
这里直接使用springboot的jdk默认的动态代理无法实现,我们需要引入AspectJ
org.springframework.boot spring-boot-starter-aop
- 启动类开启 aspectj 动态代理功能
以后所有的动态代理都是aspectj创建的(即使没有接口也可以创建动态代理),对外暴露代理对象
@EnableAspectJAutoProxy(exposeProxy=true)
- 用代理对象对本类互调
通过AopContext.currentProxy()获取代理对象
@Transactional(timeout = 30)
public void a(){
// 直接强转,然后b、c的传播行为设置就能起作用了
OrderServiceImpl orderService = (OrderServiceImpl) AopContext.currentProxy();
orderService.b();
orderService.c();
}
// REQUIRED:单纯的需要一个事务,如果 a 已经有了,就会直接使用 a 的
@Transactional(propagation = Propagation.REQUIRED)
public void b(){}
// REQUIRES_NEW:总是需要一个新的事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void c(){}
这样子就可以解决在Springboot中同一个对象内,事务方法互调默认失效的问题



