Spring调用this导致事务失效的三种解决方案

 更新时间:2026年02月26日 09:22:15   作者:五阿哥永琪  
在 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导致事务失效的资料请关注脚本之家其它相关文章!

相关文章

  • MyEclipse安装JS代码提示的教程(Spket插件)

    MyEclipse安装JS代码提示的教程(Spket插件)

    本篇文章主要介绍了MyEclipse安装JS代码提示的教程(Spket插件),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 比较java中Future与FutureTask之间的关系

    比较java中Future与FutureTask之间的关系

    在本篇文章里我们给大家分享了java中Future与FutureTask之间的关系的内容,有需要的朋友们可以跟着学习下。
    2018-10-10
  • Spring Security基于过滤器实现图形验证码功能

    Spring Security基于过滤器实现图形验证码功能

    验证码就是为了防止恶意用户采用暴力重试的攻击手段而设置的一种防护措施,接下来在Spring Security的环境中,我们可以用两种方案实现图形验证码,具体实现方法跟随小编一起看看吧
    2021-09-09
  • Java DriverManager.getConnection()获取数据库连接

    Java DriverManager.getConnection()获取数据库连接

    这篇文章主要介绍了Java DriverManager.getConnection()获取数据库连接,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 微服务链路追踪Spring Cloud Sleuth整合Zipkin解析

    微服务链路追踪Spring Cloud Sleuth整合Zipkin解析

    这篇文章主要为大家介绍了微服务链路追踪Spring Cloud Sleuth整合Zipkin解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-02-02
  • 详解@ConfigurationProperties实现原理与实战

    详解@ConfigurationProperties实现原理与实战

    这篇文章主要介绍了详解@ConfigurationProperties实现原理与实战,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • springboot整合JPA过程解析

    springboot整合JPA过程解析

    这篇文章主要介绍了springboot整合JPA过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • 详解Spring学习之编程式事务管理

    详解Spring学习之编程式事务管理

    本篇文章主要介绍了详解Spring学习之编程式事务管理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • idea 设置鼠标悬停(放上)弹出注释的方法

    idea 设置鼠标悬停(放上)弹出注释的方法

    这篇文章主要介绍了idea 设置鼠标悬停(放上)弹出注释的方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • springcloud使用consul作为配置中心

    springcloud使用consul作为配置中心

    这篇文章主要介绍了springcloud使用consul作为配置中心,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06

最新评论