阿昌教你解决在SpringBoot同一个对象内,事务方法互调默认失效问题
Posted 阿昌喜欢吃黄桃
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了阿昌教你解决在SpringBoot同一个对象内,事务方法互调默认失效问题相关的知识,希望对你有一定的参考价值。
前言
在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
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 启动类开启 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中同一个对象内,事务方法互调默认失效的问题
以上是关于阿昌教你解决在SpringBoot同一个对象内,事务方法互调默认失效问题的主要内容,如果未能解决你的问题,请参考以下文章
阿昌教你看懂mybatisplus的SqlSessionFacotry的创建过程