前四篇我们完整打通了 Spring 核心底层链路:
容器启动 → Bean 生命周期全流程 → 循环依赖三级缓存 → AOP 代理生成与执行
而 Spring 声明式事务,本质就是 AOP 的一个典型业务落地实现:它基于动态代理,在目标方法执行前后,植入事务开启、提交、回滚的横向逻辑。
接下来,我们基于 Spring 源码,完整拆解声明式事务的全流程,一次性说清:
@EnableTransactionManagement 到底做了什么?
@Transactional 注解是怎么被解析的?事务代理如何生成?
- 运行时,事务的开启、提交、回滚完整执行链路是什么?
- 7 种事务传播行为,源码层面是如何实现的?
- 面试高频的「事务失效 9 大场景」,从源码层面说清为什么会失效?
- 事务与 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 容器注册两个核心组件:
- AutoProxyRegistrar:注册事务的 AOP 代理创建器
InfrastructureAdvisorAutoProxyCreator,这是事务代理生成的核心,和 AOP 的 AnnotationAwareAspectJAutoProxyCreator 是同根同源的 BeanPostProcessor
- 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共用的父类)
@Override
public Object postProcessAfterInitialization(@Nullable Object 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(@Nullable TransactionInfo 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(@Nullable TransactionInfo 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注解是如何被解析的?
- 参数绑定、返回值处理的底层实现
希望这篇对 Spring 事务源码解析的深度拆解能帮助你彻底理解其底层原理。如果你想系统性地学习更多Java和Spring的核心技术,欢迎来云栈社区与更多开发者一起交流成长。