乐于分享
好东西不私藏

第五篇・Spring 5 源码深度拆解:事务全流程核心原理

第五篇・Spring 5 源码深度拆解:事务全流程核心原理

👋 前言

前四篇我们完整打通了 Spring 核心底层链路:

容器启动 → Bean 生命周期全流程 → 循环依赖三级缓存 → AOP 代理生成与执行

而 Spring 声明式事务,本质就是AOP 的一个典型业务落地实现:它基于动态代理,在目标方法执行前后,植入事务开启、提交、回滚的横向逻辑。

接下来,我们基于 Spring 源码,完整拆解声明式事务的全流程,一次性说清:

  1. @EnableTransactionManagement 到底做了什么?
  2. @Transactional 注解是怎么被解析的?事务代理如何生成?
  3. 运行时,事务的开启、提交、回滚完整执行链路是什么?
  4. 7 种事务传播行为,源码层面是如何实现的?
  5. 面试高频的「事务失效 9 大场景」,从源码层面说清为什么会失效?
  6. 事务与 AOP、循环依赖的关联关系是什么?

一、核心前提:Spring 事务的本质与核心组件

1. 事务的本质

Spring 声明式事务,完全基于 Spring AOP 动态代理实现

  • 容器启动时,扫描@Transactional注解,为目标 Bean 生成动态代理对象
  • 调用目标方法时,进入事务拦截器,在方法执行前开启事务,方法正常执行后提交事务,抛出异常时回滚事务
  • 整个逻辑完全复用 AOP 的代理生成、拦截器执行链路
2. 事务核心四大组件

组件

源码接口 / 类

核心作用

事务管理器

PlatformTransactionManager  

Spring 事务顶层接口,核心负责:事务开启、提交、回滚,最常用实现类DataSourceTransactionManager

事务属性定义

 TransactionDefinition  

定义事务的规则:传播行为、隔离级别、超时时间、是否只读、回滚异常规则

事务状态

 TransactionStatus  

记录事务的运行状态:是否是新事务、是否已完成、是否有保存点、是否被标记为回滚

事务拦截器

 TransactionInterceptor  

事务 AOP 的核心通知类,继承自MethodInterceptor

,在目标方法执行前后植入事务逻辑

二、事务开启的入口:@EnableTransactionManagement
我们使用 Spring 声明式事务,第一步就是在配置类上加这个注解,它是整个事务逻辑的起点

1. 注解源码拆解

@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement {    boolean proxyTargetClass() default false;    AdviceMode mode() default AdviceMode.PROXY;    int order() default Ordered.LOWEST_PRECEDENCE;}

2. 核心:TransactionManagementConfigurationSelector 做了什么?

这个选择器会根据mode属性,向 Spring 容器注册两个核心组件:

  1. AutoProxyRegistrar:注册事务的 AOP 代理创建器InfrastructureAdvisorAutoProxyCreator,这是事务代理生成的核心,和 AOP 的AnnotationAwareAspectJAutoProxyCreator是同根同源的 BeanPostProcessor
  2. ProxyTransactionManagementConfiguration:注册事务的核心 Bean
    • 事务属性解析器AnnotationTransactionAttributeSource:解析@Transactional注解的属性
    • 事务拦截器TransactionInterceptor:事务核心逻辑的载体
    • 事务通知器BeanFactoryTransactionAttributeSourceAdvisor:Spring AOP 的 Advisor,封装了切点 + 事务拦截器,是事务 AOP 的最小执行单元

关键源码佐证

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {    @Override    protected String[] selectImports(AdviceMode adviceMode) {        switch (adviceMode) {            case PROXY:                // 核心:注册代理创建器 + 事务核心配置类                return new String[] {AutoProxyRegistrar.class.getName(),                        ProxyTransactionManagementConfiguration.class.getName()};            case ASPECTJ:                return new String[] {determineTransactionAspectClass()};            default:                return null;        }    }}

3. 灵魂核心:InfrastructureAdvisorAutoProxyCreator

这个类是事务代理生成的核心,它的继承关系如下,本质就是一个 BeanPostProcessor:

InfrastructureAdvisorAutoProxyCreator        ↓AbstractAdvisorAutoProxyCreator        ↓AbstractAutoProxyCreator        ↓实现了 BeanPostProcessor 接口
它的核心作用
  • 它是一个 BeanPostProcessor,介入每一个 Bean 的生命周期
  • 容器启动时,会找到事务专用的 Advisor:BeanFactoryTransactionAttributeSourceAdvisor
  • Bean 创建时,在postProcessAfterInitialization后置处理中,判断 Bean 的方法是否有@Transactional注解,有则生成事务代理对象,替换原生 Bean
三、事务全流程第一阶段:容器启动时,事务代理生成
完整流程
容器refresh()        ↓1. invokeBeanFactoryPostProcessors:解析@EnableTransactionManagement,注册事务核心组件的BeanDefinition        ↓2. registerBeanPostProcessors:实例化InfrastructureAdvisorAutoProxyCreator,加入BeanPostProcessor列表        ↓3. finishBeanFactoryInitialization:实例化所有非懒加载单例Bean        ↓4. Bean初始化完成,进入postProcessAfterInitialization后置处理        ↓5. 匹配事务Advisor,判断方法是否有@Transactional注解        ↓6. 有事务注解 → 生成事务代理对象,替换原生Bean        ↓7. 代理对象放入单例池,对外提供服务

核心源码拆解

1. 事务注解解析:判断 Bean 是否需要生成代理

事务的切点匹配逻辑,在BeanFactoryTransactionAttributeSourceAdvisor中,核心是通过AnnotationTransactionAttributeSource解析类 / 方法上的@Transactional注解。

// 核心:解析@Transactional注解,获取事务属性protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {    // 【关键1】非public方法,直接返回null,不解析事务属性    // 这就是非public方法事务失效的源码根源!    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {        return null;    }    // 优先找实现类方法上的@Transactional    TransactionAttribute txAttr = findTransactionAttribute(method);    if (txAttr != null) {        return txAttr;    }    // 再找接口方法上的@Transactional    txAttr = findTransactionAttribute(method.getDeclaringClass());    if (txAttr != null && publicMethodOnlyForCreation) {        return txAttr;    }    // 再找类上的@Transactional    txAttr = findTransactionAttribute(targetClass);    if (txAttr != null) {        return txAttr;    }    // 没有@Transactional注解,返回null,不生成事务代理    return null;}
2. 事务代理生成入口:postProcessAfterInitialization
// AbstractAutoProxyCreator(事务和AOP共用的父类)@Overridepublic Object postProcessAfterInitialization(@NullableObject bean, String beanName) {    if (bean != null) {        Object cacheKey = getCacheKey(bean.getClass(), beanName);        // 核心:判断是否需要生成事务代理,需要则返回代理对象        return wrapIfNecessary(bean, beanName, cacheKey);    }    return bean;}

关键细节

  • 事务代理和自定义 AOP 切面代理,是同一个逻辑生成的,共用AbstractAutoProxyCreator的代理生成能力
  • 如果一个 Bean 同时有自定义 AOP 切面和@Transactional注解,会生成同一个代理对象,通过order属性控制切面和事务拦截器的执行顺序
  • 循环依赖场景下,事务代理和 AOP 代理一样,会提前在getEarlyBeanReference中生成,保证循环依赖注入的是代理对象
四、事务全流程第二阶段:运行时核心
事务代理对象生成后,当我们调用加了@Transactional的方法时,会进入事务拦截器TransactionInterceptor,执行完整的事务逻辑,这是声明式事务的核心。
核心执行总流程
调用@Transactional标注的方法        ↓进入事务代理对象的拦截器入口        ↓执行TransactionInterceptor.invoke()        ↓进入invokeWithinTransaction()【事务核心逻辑全在这里】        ↓1. 解析@Transactional注解的事务属性        ↓2. 获取事务管理器PlatformTransactionManager        ↓3. 根据传播行为,开启事务(创建/挂起事务)        ↓4. 执行目标方法        ↓5. 异常:判断是否需要回滚,执行回滚/提交        ↓6. 正常执行:提交事务,恢复被挂起的事务
核心源码拆解:事务执行的灵魂方法 invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,                                         final InvocationCallback invocation) throws Throwable {    // 1. 解析 @Transactional 事务属性    TransactionAttributeSource tas = getTransactionAttributeSource();    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);    // 2. 获取事务管理器    final PlatformTransactionManager tm = determineTransactionManager(txAttr);    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);    // 3. 方法标识    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);    // ==============================================================    // 优先判断回调式事务(JTA/WebLogic)    // ==============================================================    if (txAttr != null && ptm instanceof CallbackPreferringPlatformTransactionManager) {        ThrowableHolder throwableHolder = new ThrowableHolder();        Object result;        try {            result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {                TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);                try {                    return invocation.proceedWithInvocation();                } catch (Throwable ex) {                    if (txAttr.rollbackOn(ex)) {                        throw ex;                    } else {                        throwableHolder.throwable = ex;                        return null;                    }                } finally {                    cleanupTransactionInfo(txInfo);                }            });        } catch (ThrowableHolderException ex) {            throw ex.getCause();        }        return result;    }    // ==============================================================    // 【★ 99.9% 项目走这里 ★】标准本地事务    // ==============================================================    else {        // 1. 根据传播行为开启事务        TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);        Object retVal;        try {            // 2. 执行业务方法            retVal = invocation.proceedWithInvocation();        } catch (Throwable ex) {            // 3. 异常回滚            completeTransactionAfterThrowing(txInfo, ex);            throw ex;        } finally {            cleanupTransactionInfo(txInfo);        }        // 4. 正常提交        commitTransactionAfterReturning(txInfo);        return retVal;    }}
异常回滚:completeTransactionAfterThrowing
protected void completeTransactionAfterThrowing(@NullableTransactionInfo txInfo, Throwable ex) {    if (txInfo != null && txInfo.getTransactionStatus() != null) {        // 【关键】判断异常是否符合回滚规则        // 默认:只有RuntimeException和Error才会回滚,受检异常不会回滚        if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {            try {                // 执行回滚                txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());            }            catch (TransactionSystemException ex2) {                throw ex2;            }        }        else {            // 不符合回滚规则,依然提交事务            try {                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());            }            catch (TransactionSystemException ex2) {                throw ex2;            }        }    }}
事务提交:commitTransactionAfterReturning
protected void commitTransactionAfterReturning(@NullableTransactionInfo txInfo) {    if (txInfo != null && txInfo.getTransactionStatus() != null) {        // 执行事务提交        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());    }}

五、面试核心考点:7 种事务传播行为

事务传播行为,是 Spring 事务最核心、最高频的面试考点,它定义了:当一个带事务的方法,被另一个带事务的方法调用时,事务该如何处理

所有传播行为定义在TransactionDefinition接口中,核心 7 种,我们按源码实现逻辑分为 3 大类:

传播行为
常量名
核心行为
必需(默认)
PROPAGATION_REQUIRED
有事务就加入,没有就新建事务
支持
PROPAGATION_SUPPORTS
有事务就加入,没有就以非事务运行
强制
PROPAGATION_MANDATORY
必须在已有事务中运行,没有就抛异常
必需新建
PROPAGATION_REQUIRES_NEW
无论有没有事务,都新建一个独立事务,挂起当前事务
不支持
PROPAGATION_NOT_SUPPORTED
以非事务运行,挂起当前事务
从不
PROPAGATION_NEVER
必须非事务运行,有事务就抛异常
嵌套
PROPAGATION_NESTED
已有事务则创建嵌套事务(保存点),没有则新建事务
高频传播行为源码实现拆解

1. 默认传播行为:PROPAGATION_REQUIRED

// AbstractPlatformTransactionManager.getTransaction() 核心分支if (isExistingTransaction(transaction)) {    // 已有事务 → 加入当前事务    return handleExistingTransaction(def, transaction, debugEnabled);}// 没有事务 → 新建事务return startTransaction(def, transaction, debugEnabled, suspendedResources);

核心特点

  • 内外方法共用同一个事务,任何一个方法触发回滚,整个事务全部回滚
  • 最常用,Spring 默认选择

2. 独立事务:PROPAGATION_REQUIRES_NEW

// handleExistingTransaction 核心分支if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {    // 1. 挂起当前事务    SuspendedResourcesHolder suspendedResources = suspend(transaction);    try {        // 2. 新建一个完全独立的新事务        return startTransaction(definition, transaction, debugEnabled, suspendedResources);    }    catch (RuntimeException | Error ex) {        // 新事务异常,恢复被挂起的旧事务        resume(transaction, suspendedResources);        throw ex;    }}

核心特点

  • 内外方法是两个完全独立的事务,内方法事务提交 / 回滚,不影响外方法
  • 外方法异常回滚,不会影响已经提交的内方法事务

3. 嵌套事务:PROPAGATION_NESTED

// handleExistingTransaction 核心分支if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {    // 1. 校验是否支持嵌套事务    if (!isNestedTransactionAllowed()) {        throw new NestedTransactionNotSupportedException(...);    }    // 2. 创建保存点,嵌套事务回滚只回滚到保存点,不影响主事务    DefaultTransactionStatus status = newTransactionStatus(            definition, transaction, false, debugEnabled, suspendedResources);    status.createAndHoldSavepoint();    return status;}

核心特点

  • 基于 JDBC 的保存点Savepoint实现,嵌套事务是主事务的子事务
  • 内方法异常回滚,只会回滚到保存点,主事务可以继续执行、提交
  • 主事务异常回滚,整个嵌套事务全部回滚

六、事务失效 9 大场景

失效场景
源码级失效原因
1. 非 public 方法标注@Transactional
源码中computeTransactionAttribute方法,非 public 方法直接返回 null,不解析事务属性,不会生成代理,事务失效
2. 类内部方法调用(this 调用)
内部调用使用的是this原生对象,不是事务代理对象,不会进入事务拦截器,事务逻辑无法执行
3. 异常被 try-catch 捕获,没有抛出
事务回滚的触发点是拦截器捕获到目标方法抛出的异常,异常被捕获后,拦截器感知不到异常,不会执行回滚
4. 抛出非 RuntimeException/Error 异常
默认回滚规则rollbackOn方法,只对 RuntimeException 和 Error 回滚,受检异常(如 IOException)不会触发回滚,除非手动指定rollbackFor = Exception.class
5. 传播行为配置错误
比如使用 NOT_SUPPORTED/NEVER 传播行为,会以非事务运行;SUPPORTS 在无事务环境下,也不会开启事务
6. 标注@Transactional的类没有被 Spring 管理
没有加@Service/@Component注解,Bean 没有被 Spring 容器管理,无法生成事务代理对象,事务失效
7. 多线程场景下调用事务方法
Spring 事务是基于线程绑定的 ThreadLocal 实现的,多线程场景下,线程拿到的不是同一个数据库连接,事务无法生效
8. 数据源没有配置事务管理器
没有向容器注册PlatformTransactionManager,Spring 无法开启、提交、回滚事务,即使加了注解也无效
9. 方法被 final/static 修饰
final 方法无法被 CGLIB 代理重写,static 方法属于类,无法被代理,无法进入事务拦截器,事务失效
七、事务完整链路精简版
1. @EnableTransactionManagement 开启事务,注册事务核心组件        ↓2. 容器启动,扫描@Transactional注解,生成事务Advisor        ↓3. Bean创建时,后置处理匹配事务注解,生成代理对象        ↓4. 代理对象替换原生Bean,放入单例池        ↓5. 调用事务方法,进入TransactionInterceptor事务拦截器        ↓6. 解析事务属性,获取事务管理器,根据传播行为开启事务        ↓7. 执行目标方法        ↓8. 异常:匹配回滚规则,执行回滚/提交        ↓9. 正常:提交事务,恢复被挂起的事务
debug时核心断点位置
断点类全称
断点方法
调试内容
TransactionInterceptor invokeWithinTransaction()
事务执行全流程核心入口
AnnotationTransactionAttributeSource computeTransactionAttribute()
事务注解解析,验证非 public 方法失效
AbstractPlatformTransactionManager getTransaction()
事务开启、传播行为处理
TransactionInterceptor completeTransactionAfterThrowing()
异常回滚逻辑
TransactionInterceptor commitTransactionAfterReturning()
事务提交逻辑
八、面试高频问题

1. Spring 事务的底层实现原理是什么?

答:Spring 声明式事务基于 Spring AOP 动态代理实现,核心分为两个阶段:

  • 容器启动阶段:扫描@Transactional注解,为目标 Bean 生成动态代理对象,将事务拦截器TransactionInterceptor织入代理对象中。
  • 运行时阶段:调用事务方法时,进入事务拦截器,根据事务属性,通过事务管理器在方法执行前开启事务,方法正常执行后提交事务,抛出异常时根据回滚规则执行回滚。

2. @Transactional 注解在什么情况下会失效?

答:见本文第六部分的 9 大失效场景,核心原因分为 4 类:

  • 代理不生效:非 public 方法、内部调用、类没被 Spring 管理、final/static 方法
  • 异常处理不当:异常被捕获、抛出非回滚异常
  • 配置错误:传播行为配置错误、没有配置事务管理器
  • 特殊场景:多线程调用、数据源不支持事务

3. Spring 事务的传播行为有哪些?核心区别是什么?

答:Spring 有 7 种事务传播行为,核心分为 3 类:

  • 加入当前事务:REQUIRED、SUPPORTS、MANDATORY
  • 独立事务:REQUIRES_NEW、NOT_SUPPORTED、NEVER
  • 嵌套事务:NESTED核心区别是:REQUIRED 共用事务,一个回滚全回滚;REQUIRES_NEW 是独立事务,互不影响;NESTED 是嵌套事务,子事务回滚不影响主事务,主事务回滚子事务全回滚。

4. Spring 事务的隔离级别有哪些?和数据库隔离级别的关系?

答:Spring 定义了 5 种隔离级别,对应数据库的 4 种标准隔离级别:

  • DEFAULT:使用数据库默认的隔离级别(MySQL 默认 REPEATABLE READ)
  • READ_UNCOMMITTED:读未提交
  • READ_COMMITTED:读已提交
  • REPEATABLE_READ:可重复读
  • SERIALIZABLE:串行化Spring 的隔离级别最终会传递给数据库连接,由数据库实现隔离级别,Spring 本身不实现隔离逻辑。

5. 事务和 AOP 的关系是什么?

答:Spring 声明式事务是 AOP 的一个典型业务实现,完全复用 AOP 的核心能力:

  • 基于 BeanPostProcessor 生成动态代理对象
  • 基于 MethodInterceptor 实现事务逻辑的植入
  • 基于 Advisor 封装事务的切点和通知
  • 事务拦截器的执行,完全遵循 AOP 的通知链责任链模式

下篇预告

第六篇我们进入 Spring Web 核心考点:Spring MVC 全流程源码深度拆解

  • @EnableWebMvc到底做了什么?
  • Spring MVC 请求处理全流程,从浏览器发请求到响应返回
  • 九大组件的核心作用:HandlerMapping、HandlerAdapter、ViewResolver 等
  • @Controller/@RequestMapping注解是如何被解析的?
  • 参数绑定、返回值处理的底层实现