事务失效的几种情况以及是为什么(详解)

一.Aop失效因为事务就是通过aop来实现的

Spring 先动态生成一个子类,继承你要拦截的那个类(比如 UserService)

  • 在这个子类里重写目标方法(比如 addUser)
  • 重写的方法里面,直接去调用你写的 @Aspect 切面里的 around 方法
  • 切面的 around 里先做前置逻辑(开启事务)
  • 再通过 proceed() 调用原来的父类方法(被拦截的那个方法)
  • 最后做后置逻辑(提交 / 回滚)

AOP 基于动态代理实现,只有调用【代理对象】的方法,才会走切面的前置 → joinPoint.proceed () → 后置流程,增强才生效

1. 方法被 private 修饰(失效)

  • private 方法只能在当前类内部访问,代理对象通过反射 / 继承都调用不到这个方法
  • 代理进不去,切面流程走不起来,proceed() 根本触发不了
  • 最终:事务、AOP 增强直接失效
  • 也就是joint.proceed方法无法调用。(第四部无法完成)

2. 方法被 final /static 修饰(失效)

  • final 方法:不能被代理类重写,代理没法给方法套增强逻辑(也就是第二步没有办法完成)
  • static 方法:属于类,不属于对象实例,代理管不了静态方法
  • 结果:代理无法增强,proceed() 不执行,AOP 失效。

3. 类没有被 Spring 管理(没加 @Service/@Component 等)(失效)

  • 类没交给 Spring 管理,就不会被放进 IOC 的 Map 容器
  • Spring 不会为它生成代理对象
  • 连代理都没有,自然没有切面流程,proceed() 不存在
  • 结果:AOP 完全不生效
  • 也就是无法被继承(第一步无法完成)

4. 类内部自调用(this. 方法 ())(最经典失效)

  1. 外部调用 → 走代理对象,执行 AOP 前置逻辑
  2. 执行 joinPoint.proceed() → 进入原始目标对象(this)
  3. 原始对象里自调用方法,此时代理对象已经不存在了
  4. 自调用不走代理,第二次的 AOP 拦截完全失效
  5. 被调用方法的增强逻辑全部丢失

这个具体就是:

1. this 到底是谁?

  • 外部调用方法时,用的是Spring 生成的代理子类对象 ,此时 this = 代理对象
  • 执行 proceed() 调用父类(原类)的原方法后→ 原方法里的 this 直接变成了【原类对象(父类)】,不再是代理子类对象!

2. 父类(原类)根本调用不到子类(代理)的重写方法

  • 子类能重写父类方法,但父类永远看不到、调用不到子类的方法
  • 原类内部自己调用自己的方法(自调),比如 this.methodB()→ 这个 this 是原类对象,只能调用原类自己的原生 methodB→ 完全绕开了代理子类重写的、带 AOP 切面的方法

3. 最终结果

AOP 切面没被执行,事务、日志等增强逻辑直接失效

二、非aop的情况

  • 数据库引擎本身不支持事务MySQL 的 MyISAM 引擎就没有事务功能,不管你 Spring 事务怎么写、代理正不正常,都不可能回滚。只有 InnoDB 引擎才支持事务。

  • 异常被自己 try-catch 吃掉了,没抛出去 Spring 事务是靠捕获异常来触发回滚的。你在事务方法里把异常 catch 住,又不往外抛,Spring 根本不知道出错了,就不会回滚。

  • 抛出的异常不是 Spring 默认回滚的类型 Spring 事务默认只回滚 RuntimeException(运行时异常)和 Error 。像 IOExceptionSQLException 这种编译期受检异常 ,默认不会触发回滚,必须手动加:@Transactional(rollbackFor = Exception.class)

  • 事务传播行为配置错了比如把传播级别写成:

    • NOT_SUPPORTED:不支持事务,已存在的事务也挂起
    • NEVER:绝不允许有事务,有就抛异常事务根本不会开启,自然失效。
  • 多线程里调用事务方法 Spring 事务是和当前线程绑定的。新开线程去调用事务方法,新线程拿不到原来的事务,也走不到事务上下文,事务直接失效。

  • 没有开启事务注解驱动 老式 Spring 项目需要手动加 @EnableTransactionManagement 才能让 @Transactional 生效,没加的话注解等于白写。

相关推荐
希望永不加班7 分钟前
SpringBoot 中 AOP 实现权限校验(角色/权限)
java·spring boot·后端·spring
桌面运维家19 分钟前
IDV云桌面vDisk机房部署方案模板特性解析
java·开发语言·devops
飞翔的SA23 分钟前
从6.75%到100%!大模型Function Calling终极方案:Harness工程如何驯服
开发语言·ai·llm·harness
耿雨飞35 分钟前
Python 后端开发技术博客专栏 | 第 09 篇 GIL 深度解析与并发编程实战 -- 多线程、多进程、协程的选型
开发语言·python
Stark-C37 分钟前
NAS音乐必备神器,全平台音乐收割机!极空间部署『Go Music DL』
开发语言·后端·golang
哈密瓜刨冰40 分钟前
深入浅出 SpringMVC:核心注解全解析与实战用法
java
Ulyanov41 分钟前
像素迷宫:路径规划算法的可视化与实战
大数据·开发语言·python·算法
枫叶丹41 小时前
【HarmonyOS 6.0】ArkWeb PDF预览回调功能详解:让PDF加载状态可控可感
开发语言·华为·pdf·harmonyos
小陈工1 小时前
数据库Operator开发实战:以PostgreSQL为例
开发语言·数据库·人工智能·python·安全·postgresql·开源
耿雨飞1 小时前
Python 后端开发技术博客专栏 | 第 07 篇 元类与类的创建过程 -- Python 最深层的魔法
开发语言·python