第1篇-@Transactional注解的'前世今生'
约 2106 字大约 7 分钟
2026-05-24
四、@EnableTransactionManagement 的秘密
虽然 Spring Boot 已经帮你启用了事务管理,但了解 @EnableTransactionManagement 的工作原理,对你理解整个事务机制非常重要。
4.1 @EnableTransactionManagement 的核心逻辑
// 类路径:org.springframework.transaction.annotation.EnableTransactionManagement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class) // 【核心】导入了一个 Selector 类
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false; // 是否使用 CGLIB 代理
AdviceMode mode() default AdviceMode.PROXY; // 事务通知的应用方式(默认:代理方式)
int order() default Ordered.LOWEST_PRECEDENCE; // 事务 Advisor 的执行顺序
}关键发现:
@EnableTransactionManagement 导入了 TransactionManagementConfigurationSelector!
这个 Selector 类会根据 mode() 的值,决定导入哪个配置类。
五、TransactionManagementConfigurationSelector:选择导入哪个配置类
// 类路径:org.springframework.transaction.annotation.TransactionManagementConfigurationSelector
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() // 注册事务 Advisor、Interceptor 等
};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
}关键发现:
当 mode=PROXY(默认)时,会导入两个类:
AutoProxyRegistrar:注册一个自动代理创建器(InfrastructureAdvisorAutoProxyCreator)ProxyTransactionManagementConfiguration:注册事务相关的Advisor、Interceptor等
六、ProxyTransactionManagementConfiguration:注册事务核心组件
这个类会创建事务管理所需的三个核心组件:
TransactionAttributeSource:负责读取@Transactional注解的属性TransactionInterceptor:事务拦截器(真正执行事务逻辑的地方)BeanFactoryTransactionAttributeSourceAdvisor:事务顾问(决定哪个方法需要被拦截)
// 类路径:org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE) // 【核心】标识这是基础设施 Bean
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 创建事务 Advisor(顾问)。
*
* Advisor = Pointcut(切点) + Advice(通知)
*
* 这个 Advisor 的 Pointcut 是:
* "所有带有 @Transactional 注解的方法"
*
* 这个 Advisor 的 Advice 是:
* TransactionInterceptor(事务拦截器)
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource); // 设置属性源(用来判断哪些方法需要拦截)
advisor.setAdvice(transactionInterceptor); // 设置拦截器(真正执行事务逻辑的地方)
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order")); // 设置执行顺序
}
return advisor;
}
/**
* 创建事务属性源(TransactionAttributeSource)。
*
* AnnotationTransactionAttributeSource 会:
* 1. 查找方法或类上的 @Transactional 注解
* 2. 把注解的属性解析成 TransactionAttribute 对象
* 3. 缓存解析结果(下次就不用再解析了)
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
/**
* 创建事务拦截器(TransactionInterceptor)。
*
* 这个拦截器是事务管理的"核心执行者"。
* 它会:
* 1. 在方法执行前,开启事务
* 2. 调用方法
* 3. 如果方法正常返回,提交事务
* 4. 如果方法抛出异常,根据回滚规则决定是提交还是回滚
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager); // 设置事务管理器
}
return interceptor;
}
}七、TransactionInterceptor:事务的"执行者"
现在,我们终于来到了事务管理的"最后一环":TransactionInterceptor。
这个类的核心是 invoke() 方法。当 Spring 调用一个带有 @Transactional 注解的方法时,实际上调用的是这个 invoke() 方法。
// 类路径:org.springframework.transaction.interceptor.TransactionInterceptor
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
/**
* 【核心方法】:拦截带有 @Transactional 注解的方法。
*
* 当 Spring 调用一个带有 @Transactional 注解的方法时,
* 实际上会调用这个方法。
*
* 这个方法的执行流程:
* 1. 获取目标类(可能是 null,如果代理对象没有目标对象的话)
* 2. 调用父类的 invokeWithinTransaction() 方法
* (这个方法会处理事务的开启、提交、回滚)
* 3. 在 invokeWithinTransaction() 方法中,会调用 proceedWithInvocation()
* 也就是真正执行目标方法
*
* 【核心发现】:真正的事务逻辑不在 TransactionInterceptor 中,
* 而在它的父类 TransactionAspectSupport 的 invokeWithinTransaction() 方法中!
*/
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// 获取目标类(如果目标对象存在的话)
Class<?> targetClass = (invocation.getThis() != null ?
AopUtils.getTargetClass(invocation.getThis()) : null);
// 【核心调用】:调用父类的 invokeWithinTransaction() 方法
return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
@Override
@Nullable
public Object proceedWithInvocation() throws Throwable {
// 【核心】:这里才是真正执行目标方法的地方!
return invocation.proceed();
}
@Override
public Object getTarget() {
return invocation.getThis();
}
@Override
public Object[] getArguments() {
return invocation.getArguments();
}
});
}
}八、TransactionAspectSupport.invokeWithinTransaction():事务的核心逻辑
这个方法才是事务管理的真正核心!
它负责:
- 读取
@Transactional注解的属性 - 获取事务管理器
- 开启事务
- 执行目标方法
- 提交或回滚事务
// 类路径:org.springframework.transaction.interceptor.TransactionAspectSupport
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
/**
* 【核心方法】:在事务内调用目标方法。
*
* 这个方法的执行流程(简化版):
* 1. 获取事务属性(从 @Transactional 注解中读取)
* 2. 获取事务管理器
* 3. 如果需要,创建事务(doBegin)
* 4. 执行目标方法(proceedWithInvocation)
* 5. 如果正常返回,提交事务(commit)
* 6. 如果抛出异常,根据回滚规则决定是提交还是回滚(rollback)
*/
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 1. 获取事务属性源
TransactionAttributeSource tas = getTransactionAttributeSource();
// 2. 获取事务属性(从 @Transactional 注解中读取)
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 3. 获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
// 4. 如果是响应式事务管理器,走响应式流程(我们这里不讲)
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
// ... 省略响应式事务代码 ...
}
// 5. 转换为 PlatformTransactionManager(命令式事务管理器)
PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 6. 如果不是 CallbackPreferringPlatformTransactionManager
if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// 【核心】:创建事务(如果需要的话)
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 【核心】:执行目标方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 【核心】:异常处理(回滚)
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
// 【核心】:提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 7. 如果是 CallbackPreferringPlatformTransactionManager(比如编程式事务),走另一套流程
else {
// ... 省略 ...
}
}
}关键发现:
invokeWithinTransaction() 方法的执行流程(简化版):
1. 读取 @Transactional 注解的属性
↓
2. 获取事务管理器
↓
3. 如果需要,创建事务(createTransactionIfNecessary)
↓
4. 执行目标方法(proceedWithInvocation)
↓
5. 如果正常返回,提交事务(commitTransactionAfterReturning)
↓
6. 如果抛出异常,根据回滚规则决定是提交还是回滚(completeTransactionAfterThrowing)九、扩展点总结
在这篇文章中,我们提到了以下几个扩展点:
| 扩展点 | 场景 | 如何扩展 |
|---|---|---|
| 自定义事务管理器 | 多数据源场景,或者需要自定义事务行为 | 实现 PlatformTransactionManager 接口,或继承 DataSourceTransactionManager |
| 自定义事务属性源 | 支持自定义的事务注解 | 继承 AnnotationTransactionAttributeSource,重写相关方法 |
| 事务标签(label) | 根据标签做定制化(比如慢查询事务单独处理) | 在自定义事务管理器中,读取 TransactionDefinition.getLabels() |
| 自定义回滚规则 | 更灵活的回滚控制 | 使用 rollbackForClassName 或自定义 TransactionAttributeSource |
设置 validateExistingTransaction=true | 严格校验隔离级别 | 在事务管理器创建时设置 |
十、小结与伏笔
好了,到这里,我们已经把 @Transactional 注解的"前世今生"讲清楚了。
让我们来回顾一下整个流程:
- 你在方法上加了
@Transactional注解 - Spring Boot 通过
TransactionAutoConfiguration自动启用了事务管理 @EnableTransactionManagement导入了TransactionManagementConfigurationSelectorTransactionManagementConfigurationSelector导入了ProxyTransactionManagementConfigurationProxyTransactionManagementConfiguration创建了三个核心组件:TransactionAttributeSource(读取注解)TransactionInterceptor(事务拦截器)BeanFactoryTransactionAttributeSourceAdvisor(事务顾问)
- 当调用带有
@Transactional注解的方法时,TransactionInterceptor.invoke()会被调用 invoke()方法调用了父类TransactionAspectSupport.invokeWithinTransaction()方法- 这个方法才是事务管理的真正核心!
🔮 伏笔:事务管理器需要一个"数据源",它从哪里来?
你可能会注意到,TransactionInterceptor 需要一个 PlatformTransactionManager(事务管理器)。
而 PlatformTransactionManager 需要一个 DataSource(数据源)。
那么问题来了:
DataSource是从哪里来的?- 事务管理器是如何从数据源获取连接的?
- 连接是如何被"绑定"到当前线程的?
- MyBatis 执行 SQL 时,是如何获取到这个连接的?
这些问题,我们会在系列二(数据源系列)和系列三(MyBatis 系列)中详细讲解。
下一篇预告:《Spring 事务(二):AOP 代理 —— 事务的"隐身衣"》
在这篇文章中,我们会讲解:
- 为什么
@Transactional放在 private 方法上不生效? - Spring 是如何创建代理对象的?
- JDK 动态代理 vs CGLIB:Spring Boot 默认用哪个?
TransactionInterceptor是如何被"织入"到代理对象中的?
写在最后:这篇文章比较长,但我觉得值得。因为只有当理解了
@Transactional注解的"前世今生",你才能真正理解 Spring 事务的工作原理。如果你有什么疑问,欢迎留言讨论!