Spring事务实现原理
📌 Spring事务实现原理
Spring事务本质上并不是数据库能力,而是Spring基于AOP实现的一套事务管理框架。Spring在方法执行前开启事务,在方法执行成功后提交事务,在发生异常时回滚事务。其底层核心组件包括AOP代理、TransactionInterceptor、PlatformTransactionManager、TransactionSynchronizationManager以及数据库连接Connection。
1️⃣ 问题背景
在企业级开发中,订单创建、库存扣减、支付处理、账户转账等场景都需要保证数据一致性。
例如用户下单时需要完成以下操作:
- 创建订单
- 扣减库存
- 记录支付流水
- 发送消息通知
如果执行到一半出现异常:
- 订单创建成功
- 库存扣减成功
- 支付流水插入失败
此时数据库状态就会出现不一致问题。
为了保证多个数据库操作要么全部成功,要么全部失败,就需要事务机制。
JDBC时代需要手动管理事务:
这种方式代码侵入性极强。
Spring通过声明式事务彻底解决了这一问题。
2️⃣ 核心原理
Spring事务本质上属于AOP思想的经典应用。
开发人员只需要添加:
Spring启动时会扫描@Transactional注解。
然后为目标Bean创建代理对象。
当调用事务方法时:
真正执行事务逻辑的并不是业务方法,而是代理对象中的事务拦截器。
3️⃣ 数据结构分析
TransactionInterceptor
事务拦截器是Spring事务最核心的组件。
所有事务控制最终都会进入该方法。
PlatformTransactionManager
事务管理器负责真正操作事务。
| 实现类 | 适用场景 |
|---|---|
| DataSourceTransactionManager | JDBC事务 |
| JpaTransactionManager | JPA事务 |
| HibernateTransactionManager | Hibernate事务 |
| JtaTransactionManager | 分布式事务 |
TransactionSynchronizationManager
这是Spring事务体系中最重要的数据结构之一。
其内部大量使用ThreadLocal保存事务资源。
用于绑定:
- 数据库连接Connection
- 事务状态TransactionStatus
- 事务同步器
- 事务名称
- 只读状态
保证同一个线程中的多个DAO操作共享同一个数据库连接。
4️⃣ 算法分析
事务开启算法
进入事务方法时:
核心逻辑:
- 获取数据库连接
- 关闭自动提交
- 绑定Connection到ThreadLocal
- 创建事务状态对象
事务提交算法
业务执行成功:
执行流程:
- beforeCommit
- beforeCompletion
- connection.commit()
- afterCommit
- afterCompletion
事务回滚算法
业务抛出异常:
执行流程:
- beforeCompletion
- connection.rollback()
- afterCompletion
5️⃣ 执行流程
完整执行链路
源码执行流程
如果出现异常:
6️⃣ 实际案例
订单创建场景
执行过程:
- 开启事务
- 创建订单
- 扣减库存
- 扣减余额
- 全部成功后提交
如果余额扣减失败:
- 订单回滚
- 库存回滚
- 余额回滚
数据库最终保持一致。
事务失效案例
很多开发人员认为createOrder会开启事务。
实际上不会。
因为发生了同类内部调用。
调用过程绕过了Spring代理对象。
7️⃣ 优缺点分析
优点
- 统一事务管理
- 降低代码侵入性
- 支持声明式事务
- 支持传播行为
- 支持隔离级别配置
- 支持事务同步回调
- 与各种ORM框架无缝整合
缺点
- 依赖AOP代理
- 存在事务失效问题
- 长事务影响数据库性能
- 跨库事务实现复杂
- ThreadLocal存在资源管理成本
Spring事务与数据库事务区别
| 维度 | Spring事务 | 数据库事务 |
|---|---|---|
| 本质 | AOP封装 | 数据库能力 |
| 实现方式 | 代理模式 | Redo/Undo日志 |
| 最终执行者 | 事务管理器 | 数据库引擎 |
8️⃣ 面试常见问题
Q1:Spring事务底层如何实现?
基于AOP代理实现,通过TransactionInterceptor拦截方法调用,执行事务开启、提交和回滚。
Q2:Spring事务最终是谁提交的?
最终由PlatformTransactionManager调用JDBC Connection的commit方法提交。
Q3:Spring事务为什么使用ThreadLocal?
为了保证同一个线程中的多个DAO共享同一个数据库连接。
Q4:@Transactional为什么会失效?
同类调用、private方法、final方法、异常被吞掉、非Spring管理Bean等场景都会导致失效。
Q5:事务传播行为本质是什么?
决定当前事务是否加入已有事务,还是创建新事务。
Q6:Spring事务默认回滚哪些异常?
默认只回滚RuntimeException和Error,不回滚CheckedException。
Q7:事务注解加在private方法上有效吗?
无效,因为代理对象无法拦截private方法。
Q8:Spring事务和MySQL事务是什么关系?
Spring事务负责管理事务生命周期,真正的数据回滚和提交仍然由MySQL完成。
9️⃣ 总结
✅ Spring事务面试标准答案:
- Spring事务基于AOP实现
- @Transactional会创建代理对象
- 代理对象通过TransactionInterceptor拦截方法
- TransactionManager负责事务管理
- TransactionSynchronizationManager利用ThreadLocal绑定Connection
- 执行前开启事务
- 成功后commit
- 异常后rollback
- 最终调用的是JDBC的Connection.commit和Connection.rollback
一句话总结:Spring事务本质上是AOP + ThreadLocal + TransactionManager的组合,通过代理模式统一管理数据库连接和事务边界,最终将事务提交与回滚操作委托给数据库完成。
相关文章
-
再次理解:事务传播机制
父事务和子事务,在事务方法里调用了其它事务的方法,子事务如何执行: 1、父方法有事务。 2、父方法没有事务。 子方法事务该如何执行,有几种情况,根据这些情况,设置了七种传播基本。
NEW个对象 2025-03-06
-
事务传播
事务传播
NEW个对象 2025-01-01
-
Spring security的执行流程
Spring Security 的执行流程: 1、认证(Authentication):先经过认证过滤器 -> 认证管理器 -> 成功后存入 SecurityContextHolder 2、授权(Authorization):访问资源时经过授权过滤器 -> 权限判断 -> 允许访问或拒绝访问 3、所有请求都经过 SecurityFilterChain 过滤
NEW个对象 2025-02-27