第五篇・Spring 5 源码深度拆解:事务全流程核心原理
👋 前言
前四篇我们完整打通了 Spring 核心底层链路:
容器启动 → Bean 生命周期全流程 → 循环依赖三级缓存 → AOP 代理生成与执行
而 Spring 声明式事务,本质就是AOP 的一个典型业务落地实现:它基于动态代理,在目标方法执行前后,植入事务开启、提交、回滚的横向逻辑。
接下来,我们基于 Spring 源码,完整拆解声明式事务的全流程,一次性说清:
@EnableTransactionManagement 到底做了什么?@Transactional 注解是怎么被解析的?事务代理如何生成?-
运行时,事务的开启、提交、回滚完整执行链路是什么? -
7 种事务传播行为,源码层面是如何实现的? -
面试高频的「事务失效 9 大场景」,从源码层面说清为什么会失效? -
事务与 AOP、循环依赖的关联关系是什么?
一、核心前提:Spring 事务的本质与核心组件
1. 事务的本质
Spring 声明式事务,完全基于 Spring AOP 动态代理实现:
-
容器启动时,扫描 @Transactional注解,为目标 Bean 生成动态代理对象 -
调用目标方法时,进入事务拦截器,在方法执行前开启事务,方法正常执行后提交事务,抛出异常时回滚事务 -
整个逻辑完全复用 AOP 的代理生成、拦截器执行链路
|
组件 |
源码接口 / 类 |
核心作用 |
|
事务管理器 |
PlatformTransactionManager |
Spring 事务顶层接口,核心负责:事务开启、提交、回滚,最常用实现类 |
|
事务属性定义 |
TransactionDefinition |
定义事务的规则:传播行为、隔离级别、超时时间、是否只读、回滚异常规则 |
|
事务状态 |
TransactionStatus |
记录事务的运行状态:是否是新事务、是否已完成、是否有保存点、是否被标记为回滚 |
|
事务拦截器 |
TransactionInterceptor |
事务 AOP 的核心通知类,继承自 ,在目标方法执行前后植入事务逻辑 |
@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 容器注册两个核心组件:
- AutoProxyRegistrar:注册事务的 AOP 代理创建器
InfrastructureAdvisorAutoProxyCreator,这是事务代理生成的核心,和 AOP 的AnnotationAwareAspectJAutoProxyCreator是同根同源的 BeanPostProcessor - ProxyTransactionManagementConfiguration:注册事务的核心 Bean
-
事务属性解析器 AnnotationTransactionAttributeSource:解析@Transactional注解的属性 -
事务拦截器 TransactionInterceptor:事务核心逻辑的载体 -
事务通知器 BeanFactoryTransactionAttributeSourceAdvisor:Spring AOP 的 Advisor,封装了切点 + 事务拦截器,是事务 AOP 的最小执行单元
关键源码佐证
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {@Overrideprotected 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;}// 优先找实现类方法上的@TransactionalTransactionAttribute txAttr = findTransactionAttribute(method);if (txAttr != null) {return txAttr;}// 再找接口方法上的@TransactionaltxAttr = findTransactionAttribute(method.getDeclaringClass());if (txAttr != null && publicMethodOnlyForCreation) {return txAttr;}// 再找类上的@TransactionaltxAttr = 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. 正常执行:提交事务,恢复被挂起的事务
核心源码拆解:事务执行的灵魂方法 invokeWithinTransactionprotected 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;}}
异常回滚:completeTransactionAfterThrowingprotected 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;}}}}
事务提交:commitTransactionAfterReturningprotected void commitTransactionAfterReturning(@NullableTransactionInfo txInfo) {if (txInfo != null && txInfo.getTransactionStatus() != null) {// 执行事务提交txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());}}
五、面试核心考点:7 种事务传播行为
事务传播行为,是 Spring 事务最核心、最高频的面试考点,它定义了:当一个带事务的方法,被另一个带事务的方法调用时,事务该如何处理。
所有传播行为定义在TransactionDefinition接口中,核心 7 种,我们按源码实现逻辑分为 3 大类:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 大场景
|
|
|
|---|---|
@Transactional |
computeTransactionAttribute方法,非 public 方法直接返回 null,不解析事务属性,不会生成代理,事务失效 |
|
|
this原生对象,不是事务代理对象,不会进入事务拦截器,事务逻辑无法执行 |
|
|
|
|
|
rollbackOn方法,只对 RuntimeException 和 Error 回滚,受检异常(如 IOException)不会触发回滚,除非手动指定rollbackFor = Exception.class |
|
|
|
@Transactional的类没有被 Spring 管理 |
@Service/@Component注解,Bean 没有被 Spring 容器管理,无法生成事务代理对象,事务失效 |
|
|
|
|
|
PlatformTransactionManager,Spring 无法开启、提交、回滚事务,即使加了注解也无效 |
|
|
|
1. @EnableTransactionManagement 开启事务,注册事务核心组件↓2. 容器启动,扫描@Transactional注解,生成事务Advisor↓3. Bean创建时,后置处理匹配事务注解,生成代理对象↓4. 代理对象替换原生Bean,放入单例池↓5. 调用事务方法,进入TransactionInterceptor事务拦截器↓6. 解析事务属性,获取事务管理器,根据传播行为开启事务↓7. 执行目标方法↓8. 异常:匹配回滚规则,执行回滚/提交↓9. 正常:提交事务,恢复被挂起的事务
|
|
|
|
|---|---|---|
TransactionInterceptor |
invokeWithinTransaction() |
|
AnnotationTransactionAttributeSource |
computeTransactionAttribute() |
|
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注解是如何被解析的?-
参数绑定、返回值处理的底层实现
夜雨聆风