当前位置: 首页 > 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.dtcms.com/a/341406.html

相关文章:

  • Linux Capability 解析
  • 【81页PPT】智慧方案智能化弱电智能家居系统解决方案(附下载方式)
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘requests-html’问题
  • VPS服务器安全审计方案:从风险评估到防护实施
  • 汇编语言学习3---GDB调试
  • 【StarRocks】TabletChecker逻辑
  • 尝试给每个客户端设置一个标签身份,以此来解决非独立同分布的情况?
  • BM25 vs TF-IDF:经典文本检索方法的对比
  • 门控循环单元(GRU, Gated Recurrent Unit)
  • 压缩--RAR、7-Zip工具使用
  • 【Python】新手入门:python面向对象编程的三大特性是什么?python继承、封装、多态的特性都有哪些?
  • Jmeter接口测试
  • 30. 技术专题-锁
  • K8S-Configmap资源
  • 双模式 RTMP H.265 播放器解析:从国内扩展到 Enhanced RTMP 标准的演进
  • 媒体发稿平台哪家好?媒体新闻发稿渠道有哪些值得推荐?
  • 【知识杂记】陀螺仪直接积分就能获得角度吗?
  • 【C++】C++的类型转换
  • 《P1967 [NOIP 2013 提高组] 货车运输》
  • 多线程 + 事务传播误用导致的问题
  • 【北京迅为】iTOP-4412精英版使用手册-第三十二章 网络通信-TCP套字节
  • 如何排查服务器DNS解析失败的问题
  • TypeScript中的枚举
  • UE5分享序列播放器的停止与设置播放范围
  • 8.20作业
  • [Mysql数据库] 用户管理选择题
  • IIS访问报错:HTTP 错误 500.19 - Internal Server Error
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(一)基本代码
  • python的校园顺路代送系统
  • Seaweed-APT:AI视频生成模型,单步生成2秒钟的1280x720 24fps视频