Spring 事务管理源码分析
Spring 事务管理源码分析
为什么要了解事务源码
在实际项目中,我们经常会遇到这些问题:
- 为什么
@Transactional不生效? - 为什么在同一个类里调用自己的方法事务失效?
- Spring 是怎么控制事务的开启、提交和回滚的?
rollbackFor、Propagation、Isolation到底怎么生效的?
这些问题的根源,都藏在 Spring 的 事务代理机制 和 事务拦截器源码 里。
Spring 事务核心架构
graph TD
A["@Transactional 方法调用"]
B[TransactionInterceptor]
C[PlatformTransactionManager]
D[DataSourceTransactionManager]
E[(数据库连接)]
F[执行目标方法]
G[回滚事务]
H[提交事务]
A --> B
B --> C
C --> D
D --> E
B --> F
F --> G
F --> H
核心组件:
| 组件 | 作用 |
|---|---|
| @Transactional | 声明事务边界(告诉 Spring 哪个方法需要事务) |
| TransactionInterceptor | AOP 拦截器,拦截方法调用 |
| PlatformTransactionManager | 管理事务的接口(开启/提交/回滚) |
| DataSourceTransactionManager | 基于 JDBC 的事务实现 |
| TransactionAspectSupport | 实际处理事务逻辑的核心类 |
从 @Transactional 开始
当你在方法上加上:
1 |
|
Spring 会在容器启动时:
- 扫描到
@EnableTransactionManagement - 注册
TransactionInterceptor到 AOP 容器 - 为含
@Transactional的 Bean 生成代理对象(JDK/CGLIB) - 调用时,由拦截器接管方法执行流程
调用链分析
当你执行:
1 | orderService.createOrder(); |
执行流程:
- 代理对象拦截调用
- Spring 生成的代理类先接收调用。
- 判断方法是否有
@Transactional元信息。
- TransactionInterceptor 拦截执行
1
2
3
4
public Object invoke(MethodInvocation invocation) throws Throwable {
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
} - 获取事务属性
- 通过
TransactionAttributeSource读取注解里的信息
(如传播行为、隔离级别、rollbackFor 等)
- 调用事务管理器开启事务实际上是调用:
1
txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
1
PlatformTransactionManager#getTransaction()
- 执行目标方法
1
retVal = invocation.proceed();
- 根据结果提交或回滚如果捕获到异常:
1
commitTransactionAfterReturning(txInfo);
1
completeTransactionAfterThrowing(txInfo, ex);
核心类:TransactionAspectSupport
事务控制的核心逻辑就在这里👇
1 | protected Object invokeWithinTransaction(Method method, Class<?> targetClass, InvocationCallback invocation) { |
📌 可以看到,事务的“开、提、回滚”全在这里完成。
DataSourceTransactionManager 核心逻辑
在 DataSourceTransactionManager 中:
开启事务:
1 | Connection con = dataSource.getConnection(); |
提交事务:
1 | con.commit(); |
回滚事务:
1 | con.rollback(); |
Spring 会通过 TransactionSynchronizationManager 把当前线程和连接绑定起来,实现多层嵌套事务共享同一连接。
为什么有时 @Transactional 不生效?
常见原因总结:
| 原因 | 说明 |
|---|---|
| 1️⃣ 自调用 | 同一个类中方法互调,没经过代理 |
| 2️⃣ 方法不是 public | 事务代理默认只拦截 public 方法 |
| 3️⃣ 异常被 catch | 没抛出异常,Spring 不会回滚 |
| 4️⃣ 未被 Spring 管理 | 手动 new 出来的类没被代理 |
| 5️⃣ 数据源或事务管理器没配置正确 | Spring 没找到 PlatformTransactionManager |
调试建议
- 在
TransactionAspectSupport#invokeWithinTransaction()打断点 - 观察
txInfo对象中事务的状态 - 抛异常测试是否进入
completeTransactionAfterThrowing() - 看
DataSourceTransactionManager#doCommit()和doRollback()的执行时机
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.




