当前位置: 首页 > news >正文

Spring事务源码

深入 Spring 事务的源码实现,重点结合 AOP(面向切面编程) 的机制,从代理创建、拦截器执行、事务开启到 ThreadLocal 状态管理,完整地走一遍核心流程。


文章目录

    • 一、前置知识:Spring 事务 + AOP 的核心组件
    • 二、启动阶段:`@EnableTransactionManagement` 的作用
      • 1. `AutoProxyRegistrar`:注册自动代理机制
      • 2. `ProxyTransactionManagementConfiguration`:配置事务基础设施
    • 三、代理创建阶段:`AbstractAutoProxyCreator`
    • 四、方法调用阶段:AOP 拦截与事务逻辑
      • 1. 代理触发 `TransactionInterceptor.invoke()`
      • 2. 核心:`TransactionAspectSupport.invokeWithinTransaction`
    • 五、事务绑定到线程:`TransactionSynchronizationManager`
      • 1. `AbstractPlatformTransactionManager.getTransaction()`
      • 2. `DataSourceTransactionManager.doBegin()`:绑定连接
      • 3. `TransactionSynchronizationManager.bindResource()` 源码
    • 六、DAO 层如何获取事务连接?
    • 七、自调用失效:AOP 视角
      • 执行流程:
    • 八、图解:AOP + 事务全流程
    • 总结

一、前置知识:Spring 事务 + AOP 的核心组件

组件作用
@EnableTransactionManagement启用事务注解支持,导入 TransactionManagementConfigurationSelector
ProxyTransactionManagementConfiguration配置事务相关的 Bean(如 TransactionInterceptor
BeanPostProcessor在 Bean 初始化前后进行增强(创建代理)
AbstractAutoProxyCreator自动代理创建器基类
InfrastructureAdvisorAutoProxyCreator为基础设施(如事务)创建代理
TransactionInterceptor核心拦截器,实现 MethodInterceptor,负责事务逻辑
TransactionAspectSupport事务支持基类,包含 invokeWithinTransaction 核心方法
TransactionSynchronizationManager使用 ThreadLocal 管理事务资源(连接、状态等)

二、启动阶段:@EnableTransactionManagement 的作用

@Configuration
@EnableTransactionManagement
public class AppConfig {
}

@EnableTransactionManagement 注解会导入:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {@Overrideprotected String[] selectImports(AdviceMode adviceMode) {if (adviceMode == AdviceMode.PROXY) {// 默认使用代理模式return new String[] {AutoProxyRegistrar.class.getName(), // 注册自动代理ProxyTransactionManagementConfiguration.class.getName() // 配置事务相关 Bean};}// AspectJ 模式...}
}

1. AutoProxyRegistrar:注册自动代理机制

  • 它会向容器注册一个 InfrastructureAdvisorAutoProxyCreator
  • 这个 BeanPostProcessor 会在 Bean 初始化后,判断是否需要创建代理。

2. ProxyTransactionManagementConfiguration:配置事务基础设施

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {// 创建事务切面:Advisor = Pointcut + AdviceBeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource()); // 解析 @Transactionaladvisor.setAdvice(transactionInterceptor()); // 设置拦截器advisor.setOrder(platformTransactionManager.getOrder());return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {// 创建事务拦截器TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());interceptor.setTransactionManager(transactionManager());return interceptor;}
}

关键点

  • TransactionInterceptorMethodInterceptor,负责拦截方法调用。
  • BeanFactoryTransactionAttributeSourceAdvisorAdvisor,包含:
    • Pointcut:匹配所有标注 @Transactional 的方法。
    • Advice:即 TransactionInterceptor

三、代理创建阶段:AbstractAutoProxyCreator

当一个 Bean(如 UserService)被创建并初始化后,InfrastructureAdvisorAutoProxyCreator 会执行:

// AbstractAutoProxyCreator.java
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {// 1. 获取所有匹配的 Advisor(包括事务 Advisor)List<Advisor> advisors = findEligibleAdvisors(bean.getClass(), beanName);// 2. 如果有匹配的 Advisor,则创建代理if (!advisors.isEmpty()) {return createProxy(bean, beanName, advisors);}return bean;
}
  • 如果 UserService 类或方法上有 @TransactionalBeanFactoryTransactionAttributeSourceAdvisor 会被匹配。
  • Spring 使用 JDK 动态代理(实现接口)或 CGLIB(继承类)创建代理对象。

四、方法调用阶段:AOP 拦截与事务逻辑

当你调用 userService.saveUser() 时,实际调用的是 代理对象

1. 代理触发 TransactionInterceptor.invoke()

// TransactionInterceptor.java
public Object invoke(MethodInvocation invocation) throws Throwable {// 调用父类 TransactionAspectSupport 的 invokeWithinTransactionreturn invokeWithinTransaction(invocation.getMethod(), invocation.getThis().getClass(),() -> invocation.proceed());
}

2. 核心:TransactionAspectSupport.invokeWithinTransaction

// TransactionAspectSupport.java
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,final InvocationCallback invocation) throws Throwable {// 1. 解析 @Transactional 注解,得到事务属性TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);// 2. 获取事务管理器PlatformTransactionManager tm = determineTransactionManager(txAttr);// 3. 开启事务TransactionStatus status = tm.getTransaction(txAttr);Object retVal;try {// 4. 执行目标方法(你的业务代码)retVal = invocation.proceed(); // 👈 真正执行 userService.saveUser()} catch (Throwable ex) {// 5. 异常:回滚completeTransactionAfterThrowing(txAttr, ex);throw ex;} finally {// 6. 清理事务信息cleanupTransactionInfo(txInfo);}// 7. 成功:提交commitTransactionAfterReturning(txAttr, status);return retVal;
}

invocation.proceed() 是 AOP 链式调用的关键,它会继续执行下一个拦截器,最终到达目标方法。


五、事务绑定到线程:TransactionSynchronizationManager

我们聚焦 tm.getTransaction(txAttr) 的内部实现。

1. AbstractPlatformTransactionManager.getTransaction()

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) {// 1. 获取事务对象(如 DataSourceTransactionManager 创建 ConnectionHolder)Object transaction = doGetTransaction();// 2. 判断当前线程是否已有事务if (isExistingTransaction(transaction)) {// 已有事务,根据传播行为处理(如 REQUIRED 加入,REQUIRES_NEW 挂起并新建)return handleExistingTransaction(...);}// 3. 没有事务,新建if (def.getPropagationBehavior() == PROPAGATION_REQUIRED) {return startTransaction(def, transaction, debug, suspendedResources);}
}

2. DataSourceTransactionManager.doBegin():绑定连接

protected void doBegin(Object transaction, TransactionDefinition definition) {Connection con = dataSource.getConnection();// 将连接包装为 ConnectionHolderDataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;txObject.setConnectionHolder(new ConnectionHolder(con), true);// 🌟 核心!绑定到 ThreadLocalTransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());// 标记当前线程有活跃事务TransactionSynchronizationManager.setActualTransactionActive(true);// 设置隔离级别、只读等TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(definition.getIsolationLevel());
}

3. TransactionSynchronizationManager.bindResource() 源码

private static final ThreadLocal<Map<Object, Object>> resources =new NamedThreadLocal<>("Transactional resources");public static void bindResource(Object key, Object value) throws IllegalStateException {Map<Object, Object> map = resources.get();if (map == null) {map = new HashMap<>();resources.set(map);}map.put(key, value);
}

关键点:数据库连接 Connection 被绑定到了当前线程的 ThreadLocal<Map> 中,键是 DataSource


六、DAO 层如何获取事务连接?

当你在 UserDao 中使用 JdbcTemplateSqlSession 时:

jdbcTemplate.update("UPDATE users SET name = ? WHERE id = ?", "Tom", 1);

JdbcTemplate 内部会:

// JdbcTemplate.java
protected Connection getConnection() {// 从 TransactionSynchronizationManager 获取当前事务的连接return TransactionSynchronizationManager.getResource(dataSource);
}

因为前面 doBegin() 已经把连接 put 进去了,所以这里能拿到同一个连接,保证事务一致性。


七、自调用失效:AOP 视角

@Service
public class UserService {public void methodA() {methodB(); // ❌ this.methodB(),不是代理调用!}@Transactionalpublic void methodB() {// 业务代码}
}

执行流程:

外部调用 userService.methodA()
│
└─ 代理对象拦截 → TransactionInterceptor.invoke()│├─ 开启事务(如果 methodA 也有 @Transactional)│├─ 执行 methodA() 业务│   ││   └─ this.methodB() → JVM 直接调用 UserService.methodB()│       ││       └─ ❌ 没有经过代理 → TransactionInterceptor 不执行│       └─ @Transactional 完全被忽略!│└─ 提交/回滚事务

结论:只有通过代理对象调用的方法,才会触发 TransactionInterceptor@Transactional 才会生效。


八、图解:AOP + 事务全流程

[外部调用]↓
[代理对象] ←——— AOP 创建↓
TransactionInterceptor.invoke()↓
TransactionAspectSupport.invokeWithinTransaction()↓
AbstractPlatformTransactionManager.getTransaction()↓
DataSourceTransactionManager.doBegin()↓
TransactionSynchronizationManager.bindResource(connection)  // ThreadLocal 绑定↓
invocation.proceed() → 执行目标方法↓
UserDao 使用 JdbcTemplate → 从 ThreadLocal 获取 connection↓
method 执行完成↓
commitTransactionAfterReturning() / completeTransactionAfterThrowing()↓
清理 ThreadLocal

总结

阶段核心机制
启动@EnableTransactionManagement 导入 TransactionInterceptorAdvisor
代理创建BeanPostProcessor 为带 @Transactional 的 Bean 创建代理(JDK/CGLIB)
方法调用代理触发 TransactionInterceptor.invoke()
事务开启TransactionAspectSupport.invokeWithinTransaction() 调用 getTransaction()
线程绑定TransactionSynchronizationManager.bindResource() 使用 ThreadLocal 存储连接
DAO 访问JdbcTemplate 等从 ThreadLocal 获取当前事务连接
自调用失效this.method() 绕过代理,TransactionInterceptor 无法拦截

🔁 一句话总结:Spring 事务 = AOP 动态代理 + TransactionInterceptor 拦截 + TransactionSynchronizationManagerThreadLocal 状态管理

理解这三者如何协同工作,就真正掌握了 Spring 事务的“内核”。

http://www.lryc.cn/news/626842.html

相关文章:

  • PyTorch API 1
  • 【数据结构】递归与非递归:归并排序全解析
  • 第一章:认识 CAD 图形文件 —— DXF 格式
  • 车载软件架构 --- 赢得汽车软件开发竞赛
  • 好家园房产中介网后台管理完整(python+flask+mysql)
  • Scikit-learn 预处理函数分类详解
  • 【Task02】:四步构建简单rag(第一章3节)
  • 第R6周:LSTM实现糖尿病探索与预测
  • 深度学习核心技巧与实战指南
  • 机器学习中的数据处理技巧
  • Node.js中的Prisma应用:现代数据库开发的最佳实践
  • 关联规则挖掘3:Eclat算法——等价类转换(Equivalence Class Transformation)
  • Simulink实现RELS递推最小二乘算法
  • 【机器学习】什么是损失景观(Loss Landscape)?
  • 漏扫 js 里面包含一些敏感内容 利用二进制加密 保持原始内容不变 又能过漏扫
  • 亚马逊蓝海掘金:以需供比为锚点的精准选品策略
  • 高压柜无线测温:给智能化配电室装上“智能体温监测仪”
  • Leetcode 深度优先搜索 (11)
  • C语言---分隔符、常量、注释、标识符、关键字、空格
  • 笔试——Day44
  • 域名加白怎么做
  • 实战:本地大模型+function Calling,获取北京天气
  • 保姆级Debezium抽取SQL Server同步kafka
  • JSON::Value 功能详解:从三目运算符到高级用法
  • Pytest项目_day20(log日志)
  • PyTorch API 2
  • GPT-5 上线风波深度复盘:从口碑两极到策略调整,OpenAI 的变与不变
  • C++开发/Qt开发:单例模式介绍与应用
  • 拓扑排序判断环 P1347 排序题解
  • 第二十七天:游戏组队问题