news 2026/5/2 20:59:28

10|SpringBoot 自动配置原理 一句话讲清: 1. 启动类注解 @SpringBootApplication 2. 内部 @EnableAutoConfiguration 3. 读取 M

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
10|SpringBoot 自动配置原理 一句话讲清: 1. 启动类注解 @SpringBootApplication 2. 内部 @EnableAutoConfiguration 3. 读取 M

@Transactional 失效场景:面试最爱挖的 6 个坑

面试官:“你遇到过@Transactional失效的情况吗?”
你:“遇到过。比如方法不是 public、同类中方法互相调用、异常被 try-catch 吞掉、传播属性设置错误、数据库引擎不支持事务、抛出了非 RuntimeException 异常等。”
面试官:“那你能具体说说为什么同类调用会失效吗?底层原理是什么?”
你:“……”

很多人能列举失效场景,但一问到“为什么”就卡壳了。本文从 Spring AOP 代理原理出发,把 6 个常见失效场景彻底讲透,并给出解决方案。


一、@Transactional失效的本质原因

Spring 事务管理基于AOP 动态代理。当一个 Bean 被代理后,只有通过代理对象调用方法,才会触发事务增强逻辑。直接通过this调用目标对象的方法,不会经过代理,因此@Transactional完全无效。

理解了这个根本原因,下面 6 个失效场景就都能解释通了。


二、6 大失效场景详解

场景 1:方法非 public

现象@Transactional标注在privateprotecteddefault访问权限的方法上,事务不生效。

原理:Spring 默认使用 CGLIB 或 JDK 动态代理。对于 CGLIB,它通过生成子类覆盖目标方法实现增强,但private方法无法被子类覆盖;对于 JDK 动态代理,代理类只实现接口方法,private方法不在接口中。Spring 会忽略非public方法的@Transactional注解,且不报错。

@ServicepublicclassOrderService{@Transactional// 失效!方法不是 publicprivatevoidupdateOrder(){}}

解决方案:确保事务方法声明为public。如果需要保护内部方法,可以将其提取到单独的 Service 类中。

场景 2:同类中方法互相调用(自调用)

现象:同一个类中,方法 A(无@Transactional)调用方法 B(有@Transactional),事务不生效。

@ServicepublicclassOrderService{publicvoidmethodA(){methodB();// 直接调用,不会经过代理,事务失效}@TransactionalpublicvoidmethodB(){}}

原理methodA通过this.methodB()调用,this是原始对象,不是代理对象。代理对象只有在外部调用时才会生效。

解决方案

  1. 注入自身代理(推荐):
@ServicepublicclassOrderService{@AutowiredprivateOrderServiceselfProxy;publicvoidmethodA(){selfProxy.methodB();// 通过代理调用}}
  1. 从 Spring 容器中获取代理
OrderServiceproxy=(OrderService)AopContext.currentProxy();proxy.methodB();
  1. 将方法 B 提取到另一个 Service(最清晰,符合单一职责)。

场景 3:异常被 try-catch 吃掉,没有抛出

现象:方法内部 catch 了异常但没有重新抛出,事务不会回滚。

@TransactionalpublicvoidupdateOrder(){try{// 执行数据库操作,可能抛出异常}catch(Exceptione){log.error("异常被捕获,未抛出",e);// 没有重新抛出,事务会正常提交!}}

原理:Spring 事务管理器通过检测方法抛出的异常来决定是否回滚。如果异常被捕获且未重新抛出,Spring 认为方法执行成功,会提交事务。

解决方案

  • 要么在 catch 块中抛出异常(throw e;
  • 要么手动标记事务为回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

场景 4:传播属性设置错误

现象:使用了Propagation.NOT_SUPPORTEDPropagation.NEVER等传播行为,导致事务不存在。

@Transactional(propagation=Propagation.NOT_SUPPORTED)publicvoidmethodB(){}// 这个方法永远在非事务环境下执行

如果调用方有事务,会被挂起;如果调用方无事务,也以非事务执行。总之,方法 B 内不会有事务。

解决方案:确认传播行为符合预期。大部分业务场景应使用默认的REQUIRED

场景 5:数据库引擎不支持事务

现象:代码和配置都没问题,但事务就是不生效。常见于 MySQL 使用 MyISAM 引擎。

原理:MyISAM 引擎不支持事务(没有 undo log),而 InnoDB 支持。如果表的存储引擎是 MyISAM,无论怎么配置@Transactional,都不会有回滚效果。

解决方案

  • 检查表引擎:SHOW TABLE STATUS WHERE Name = 'your_table';
  • 修改为 InnoDB:ALTER TABLE your_table ENGINE=InnoDB;
  • 在创建表时指定引擎:ENGINE=InnoDB

场景 6:抛出了非 RuntimeException 异常

现象:方法抛出了Exception(非RuntimeException子类),事务没有回滚。

@Transactionalpublicvoidmethod()throwsException{// ...thrownewException("checked exception");}

原理:Spring 事务回滚的默认行为是:只对RuntimeExceptionError进行回滚,对checked exceptionException的子类但非RuntimeException)默认不进行回滚。

解决方案

  • 配置rollbackFor属性:
@Transactional(rollbackFor=Exception.class)
  • 或者抛出RuntimeException的子类。

三、其他容易被忽略的失效场景

7. 多数据源配置错误

如果配置了多个TransactionManager,但没有指定@Transactional("txManagerName"),Spring 可能使用了错误的事务管理器,导致事务不生效。

8. 事务方法所在的 Bean 没有被 Spring 管理

类上没有@Service@Component等注解,或者通过new手动创建对象,@Transactional完全无效。

9. 切面顺序导致事务增强被覆盖

如果自定义了 AOP 切面,且执行顺序在事务切面之前,且切面内部 catch 了异常,可能导致事务切面无法接收到异常。

10. 方法内部使用了异步线程

在事务方法内新开一个线程执行数据库操作,新线程的数据库连接与当前事务不绑定,操作不会参与当前事务。


四、如何快速排查事务失效?

  1. 检查方法是否为 public
  2. 检查是否通过代理调用(排除自调用)
  3. 检查异常是否被吞掉(看日志)
  4. 检查传播行为(默认 REQUIRED)
  5. 检查数据库引擎(InnoDB)
  6. 检查异常类型(是否在 rollbackFor 范围内)
  7. 开启 Spring 事务日志
logging.level.org.springframework.transaction=DEBUG logging.level.org.springframework.orm.jpa=DEBUG

观察日志中事务的创建、提交、回滚信息。


五、总结表

失效场景根本原因解决方案
方法非 public代理无法拦截非 public 方法改为 public
同类自调用未通过代理对象调用注入自身代理或拆分到新类
异常被 catch 吃掉Spring 未感知到异常抛出异常或手动回滚
传播属性错误事务不存在(如 NOT_SUPPORTED)确认传播行为,默认 REQUIRED
数据库引擎不支持MyISAM 等不支持事务改为 InnoDB
非 RuntimeException默认不回滚 checked exception配置 rollbackFor = Exception.class

一句话记住失效场景非 public、自调用、吞异常、传播错、引擎差、异常选错

希望这篇文章能帮你避开@Transactional的常见陷阱,在面试和开发中都能从容应对。如果需要进一步了解分布式事务或编程式事务,欢迎继续讨论。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 6:32:38

Qwen3-Embedding-4B降本部署案例:单卡RTX3060实现800 doc/s高吞吐

Qwen3-Embedding-4B降本部署案例:单卡RTX3060实现800 doc/s高吞吐 1. 模型概述 Qwen3-Embedding-4B是阿里Qwen3系列中专注于文本向量化的4B参数双塔模型,于2025年8月开源。该模型定位为"中等体量、32k长文、2560维向量、119语通用"的文本嵌入…

作者头像 李华
网站建设 2026/5/2 20:58:32

Stable Diffusion Anything V5应用场景:电商配图、社交内容一键生成

Stable Diffusion Anything V5应用场景:电商配图、社交内容一键生成 大家好,今天我们来聊聊一个能帮你“解放双手”的AI工具——Stable Diffusion Anything V5。如果你正在为电商配图、社交媒体内容创作而烦恼,每天需要处理大量图片素材&…

作者头像 李华
网站建设 2026/4/16 6:31:33

【一图看懂】手机里的SIM卡到底能查出什么? | 手机篇

我们每天离不开手机,小小 SIM 卡不止用来打电话上网,更是藏着海量个人信息的 “数字身份证”。在电子数据取证领域,SIM 卡从来都不只是一张电话卡,更是会说话的证据载体。它默默记录着通话、短信、基站位置、身份信息等关键痕迹&a…

作者头像 李华
网站建设 2026/4/16 6:20:30

Nunchaku FLUX.1-dev保姆级教程:ComfyUI自定义节点开发入门

Nunchaku FLUX.1-dev保姆级教程:ComfyUI自定义节点开发入门 1. 前言:为什么选择Nunchaku FLUX.1-dev? 如果你正在ComfyUI里玩AI绘画,可能已经试过不少模型了。但最近有个新家伙特别火——Nunchaku FLUX.1-dev。这可不是普通的文…

作者头像 李华
网站建设 2026/4/16 6:16:36

在线图片处理工具 多功能图片编辑格式转换 pc+h5自适应

内容目录一、详细介绍二、效果展示1.部分代码2.效果图展示一、详细介绍 在线图片处理工具 多功能编辑格式转换HTML源码 实现了所有图片处理功能包括: 完整的图片处理功能集: 图片压缩(可调整质量) 图片编辑(亮度、对…

作者头像 李华