阿昌教你解决在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同一个对象内,事务方法互调默认失效问题的主要内容,如果未能解决你的问题,请参考以下文章

阿昌教你自定义注解验证Bean对象

阿昌教你自定义注解验证Bean对象

阿昌教你看懂mybatisplus的SqlSessionFacotry的创建过程

阿昌教你看懂mybatisplus的SqlSessionFacotry的创建过程

阿昌教你看懂mybatisplus的sql语句的创建过程

阿昌教你看懂mybatisplus的sql语句的创建过程