part1-framework-collaboration
约 757 字大约 3 分钟
2026-05-24
系列文章:《深入Spring事务与数据源:从注解到数据库连接的全链路解析》
系列四第1篇:三大框架协作全链路源码分析
基于版本:Spring 5.3.x + Druid 1.2.x + MyBatis 3.5.x
前置阅读:系列一、二、三所有文章
前言
经过前面三个系列的深度剖析,咱们分别搞清楚了:
- 系列一:Spring事务管理的完整机制
- 系列二:Druid连接池的全链路源码
- 系列三:MyBatis执行器的执行流程
但是,这三个框架是怎么协作的?一个带@Transactional的Service方法,从被调用到最终执行SQL,中间经历了什么?
今天这篇文章,咱们就从更高的角度,把这三个框架串起来,看看它们是怎么完美协作的。
一、完整的执行链路
从一个带@Transactional的Service方法开始:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void createUser(User user) {
userMapper.insert(user);
}
}当你调用userService.createUser(user)时,发生了什么?
第1阶段:Spring事务拦截
↓
UserService是代理对象(CGLIB)
↓
TransactionInterceptor.invoke()
↓
invokeWithinTransaction()
↓
创建事务(如果需要)
↓
第2阶段:获取数据库连接
↓
DataSourceTransactionManager.doBegin()
↓
DruidDataSource.getConnection()
↓
从连接池获取Connection
↓
关闭autocommit,开启事务
↓
绑定到ThreadLocal
↓
第3阶段:MyBatis执行SQL
↓
userMapper.insert()(代理对象)
↓
MapperProxy.invoke()
↓
SqlSession.insert()
↓
Executor.update()
↓
SimpleExecutor.doUpdate()
↓
PreparedStatementHandler
↓
从ThreadLocal获取Connection(同一个!)
↓
创建PreparedStatement
↓
设置参数
↓
执行SQL
↓
第4阶段:事务提交
↓
业务方法执行成功
↓
TransactionInterceptor提交事务
↓
Connection.commit()
↓
释放连接(归还到连接池)二、关键点:同一个Connection
整个流程中,最关键的是什么?
同一个Connection!
// 第1次:事务开启时获取连接
// DataSourceTransactionManager.doBegin()
Connection con = dataSource.getConnection(); // 从Druid获取连接1
TransactionSynchronizationManager.bindResource(dataSource, connectionHolder); // 绑定到ThreadLocal
// 第2次:MyBatis执行SQL时获取连接
// SpringManagedTransaction.getConnection()
Connection con = DataSourceUtils.getConnection(dataSource); // 从ThreadLocal获取连接1
// 返回的是同一个连接!这就是为什么MyBatis的SQL能在Spring事务中执行的原因——它们用的是同一个Connection!
三、ThreadLocal:连接传递的桥梁
ThreadLocal在整个流程中起到了桥梁的作用:
事务管理器 MyBatis
↓ ↓
获取连接 获取连接
↓ ↓
绑定到ThreadLocal 从ThreadLocal获取
↓ ↓
└───────────┬──────────────┘
↓
同一个Connection代码实现:
// 事务管理器绑定
TransactionSynchronizationManager.bindResource(dataSource, connectionHolder);
// MyBatis获取
ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
Connection conn = holder.getConnection();四、系列四后续文章预告
这只是系列四的第1篇,后续文章还会包括:
第2篇:常见异常分析与根因定位
- Connection泄漏
- 事务不回滚
- 连接池满
- 慢SQL
第3篇:性能调优最佳实践
- 事务优化
- 连接池调优
- MyBatis优化
- 全链路调优
第4篇:全链路知识点总结
- 核心概念总结
- 设计模式总结
- 学习建议
敬请期待!
参考资料
- Spring Framework 5.3.x 源码
- Druid 1.2.x 源码
- MyBatis 3.5.x 源码
- 《Spring源码深度解析》
- 《MyBatis技术内幕》