Spring 事务全链路解析(一):@Transactional 注解的_前世今生_
约 4430 字大约 15 分钟
2026-05-25
在日常开发中,我们基于 SpringBoot 框架只需要在 Service 方法上添加一个@Transactional注解,就能轻松实现事务管理。那你有没有想过,为什么在一个方法上轻轻加个 @Transactional 注解,这个方法就有了事务能力?
在这个简单的注解背后,到底是谁在"偷偷"帮我们管理连接、提交、回滚?今天,我们就从这个选题开始,一步步揭开 Spring 事务的神秘面纱。
从一个简单的 Service 方法开始
先来看一个最最基础的场景 —— 你肯定写过类似的代码:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 看这里!就是这么一个注解
@Transactional
public void createUser(User user) {
userMapper.insert(user);
// 想想看,如果这里抛了异常,数据会回滚吗?
}
}你可能会说:"这有啥好说的,加个 @Transactional 不就完事了?"
但是,真的是这样吗?
让我来问几个问题:
@Transactional只是个注解,它自己不会"干活"吧?那是谁在"看"这个注解?- 如果我在同一个类的另一个方法里调用这个
createUser(),事务还会生效吗?(这是个经典坑,后面会详细讲) - Spring 是怎么在方法执行前"偷偷"开启事务,在方法执行后"偷偷"提交或回滚的?
要想回答这些问题,我们得从 @Transactional 注解的源码开始,一层层剥开它的"前世今生"。
@Transactional 注解的核心属性
先上注解的源码来看一下它都能干什么
// 类路径:org.springframework.transaction.annotation.Transactional
@Target({ElementType.TYPE, ElementType.METHOD}) // 可以标注在类或方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时保留,这样 Spring 才能反射读取到
@Inherited // 可以被子类继承
@Documented // 会出现在 JavaDoc 中
public @interface Transactional {
// ===== 核心属性 =====
@AliasFor("transactionManager")
String value() default ""; // 事务管理器的别名
@AliasFor("value")
String transactionManager() default ""; // 指定使用哪个事务管理器
String[] label() default {}; // 事务标签(Spring 5.3+)
Propagation propagation() default Propagation.REQUIRED; // 传播行为(默认:REQUIRED)
Isolation isolation() default Isolation.DEFAULT; // 隔离级别(默认:使用数据库默认)
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; // 超时时间(秒)
String timeoutString() default ""; // 超时时间(字符串形式,支持占位符)
boolean readOnly() default false; // 是否只读事务
Class<? extends Throwable>[] rollbackFor() default {}; // 指定哪些异常必须回滚
String[] rollbackForClassName() default {}; // 指定哪些异常(类名)必须回滚
Class<? extends Throwable>[] noRollbackFor() default {}; // 指定哪些异常必须不回滚
String[] noRollbackForClassName() default {}; // 指定哪些异常(类名)必须不回滚
}核心属性:
@AliasFor("transactionManager"):value和transactionManager是互为别名的关系。也就是说:@Transactional("txManager") // 等价于 @Transactional(transactionManager = "txManager")
::: tip指定事务管理器的意义在哪? @Transactional 注解中可以指定事务管理器,这就表明我们可以声明多个事务管理器,并且可以去自定义事务管理器,比如多数据源场景,或者需要自定义事务行为。 :::
propagation传播行为属性:决定了"如果当前已经有一个事务了,我这个新方法是加入旧事务,还是自己开一个新事务?"- 默认值
REQUIRED:没有就新建,有就加入 - 我们 下下篇文章 会专门讲这个
- 默认值
isolation属性:决定了"一个事务能看见另一个事务未提交的数据吗?"- 默认值
DEFAULT:使用数据库的默认隔离级别(MySQL 默认是REPEATABLE_READ) - 我们 下下篇文章 会专门讲这个
- 默认值
rollbackFor属性:默认情况下,遇到RuntimeException和Error时回滚,遇到检查异常(checked exception)不回滚。- 如果你想让检查异常也触发回滚,可以:
@Transactional(rollbackFor = Exception.class) - 异常类图
- 如果你想让检查异常也触发回滚,可以:

Spring Boot 是如何创建事务管理器的?
注解的源码看完了,我们都知道事务都是归事务管理器进行管理,并且在此处可以指定对应的事务管理器,那你知道事务管理器是怎么被创建的吗?Spring 是怎么"知道"这个注解要关联的事务管理器呢?
答案就是:Spring Boot 的自动装配机制。
TransactionAutoConfiguration(事务自动配置类)
通过分析可以定位到 spring-boot-autoconfigure 包下的 TransactionAutoConfiguration 自动配置类,这个类是 Spring Boot 自动配置事务的入口。让我给你看看它的核心逻辑(只展示核心方法):
// 类路径:org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(PlatformTransactionManager.class)
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {
/**
* 【核心内部类】:启用事务管理的配置。
*
* 这个类上加了 @EnableTransactionManagement 注解!
* 也就是说,只要使用 Spring Boot 框架,就会自动帮你启用事务管理。
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(TransactionManager.class) // 【条件】只有当容器中有 TransactionManager Bean 时,才生效
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class) // 【条件】只有当没有手动配置事务管理时,才生效
public static class EnableTransactionManagementConfiguration {
/**
* JDK 动态代理配置。
*
* 当 spring.aop.proxy-target-class=false 时,使用 JDK 动态代理。
*/
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
public static class JdkDynamicAutoProxyConfiguration {
}
/**
* CGLIB 代理配置(默认)。
*
* 当 spring.aop.proxy-target-class=true(默认值)时,使用 CGLIB 代理。
*
* 【注意】:matchIfMissing = true,也就是说,默认会匹配这个配置!
* 这就是为什么 Spring Boot 默认使用 CGLIB 代理。
*/
@Configuration(proxyBeanMethods = false)
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
matchIfMissing = true) // 【核心】默认匹配!
public static class CglibAutoProxyConfiguration {
}
}
}Spring Boot 中默认帮我们加了 @EnableTransactionManagement 注解,所以事务配置会自动生效!我们不需要再手动加 @EnableTransactionManagement , 除非需要自定义一些行为。
同时观察到 Spring Boot 默认使用 CGLIB 代理,因为 matchIfMissing = true,所以默认会匹配 CglibAutoProxyConfiguration,这就是为什么 Service 不需要实现接口,事务也能生效的原因。
::: tip如何去选择哪种代理模式呢?
这实际取决于具体的应用需求和目标类的设计,让我们简单看下其不同代理模式下的特点。
JDK 动态代理
- 接口驱动: JDK 动态代理要求目标对象必须实现至少一个接口。
- 性能: 相对于 CGLIB,JDK 动态代理的性能略低,因为它是通过反射机制来调用方法。
- 灵活性: 适用于只需要拦截接口方法的情况。
默认情况下,如果目标类实现了接口,Spring 使用 JDK 动态代理。
CGLIB 代理
- 继承驱动: CGLIB 代理通过继承目标类来创建代理对象,因此不需要目标类实现接口。
- 性能: CGLIB 代理的性能通常优于 JDK 动态代理,因为它是在运行时生成字节码,而不是通过反射。
- 灵活性: 适用于需要拦截所有方法(包括私有方法)的情况。
CGLIB 之所以只能继承使用,根本原因在于 其核心实现原理是通过继承目标类生成子类来实现代理,这使其能够代理没有接口的普通类,但同时也带来了无法代理 final 类和方法的限制。
总体来说,JDK 动态代理适用于接口驱动的场景,性能稍差但更灵活。CGLIB 代理适用于非接口驱动的场景,性能更好但灵活性较低。 :::
@EnableTransactionManagement 的秘密
对于一些有资历的程序员来说,在没有 Spring Boot 以前,Spring 框架还需要我们手动开启 @EnableTransactionManagement 事务管理器,现在都交给了 Spring Boot 去帮我们启用了事务管理,让我们更加关注于业务开发上的工作。
但是对于一个程序员来说,深入了解 @EnableTransactionManagement 的工作原理,对理解整个事务机制非常重要,从而去更加契合我们的业务开发。
@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 的 Bean 实例信息, 与我们常说的自动装配 @EnableAutoConfiguration 注解导入 @Import(AutoConfigurationPackages.Registrar.class) 的实现原理一模一样,见名知义,由此可推理,这个类必定做了一些 Bean 实例加载的动作,让我们接下来继续分析。
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;
}
}
}AdviceModeImportSelector 类中,会加载声明的 EnableTransactionManagement 注解元数据,获取 mode 属性,并调用上面代码中的 TransactionManagementConfigurationSelector #selectImports 方法,默认是 AdviceMode.PROXY 模式,会导入两个类:
AutoProxyRegistrar:注册一个自动代理创建器InfrastructureAdvisorAutoProxyCreatorProxyTransactionManagementConfiguration:注册事务相关的Advisor、Interceptor等
AutoProxyRegistrar: 自动代理注册器
AutoProxyRegistrar 主要的作用是向 Spring 容器中注册了一个 InfrastructureAdvisorAutoProxyCreator 的 Bean 实例,它继承了AbstractAdvisorAutoProxyCreator,这个类的主要作用就是 开启自动代理 。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(
importingClassMetadata, annType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null
&& AdviceMode.class == mode.getClass()
&& Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
if (mode == AdviceMode.PROXY) {
// 注册关键组件:InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
}
}InfrastructureAdvisorAutoProxyCreator 是 Spring AOP 的核心组件,它实现了 BeanPostProcessor 接口,会在 Bean 初始化过程中介入,为符合条件的 Bean 创建代理对象,其本质就是判断当前某个 Bean 是否有匹配的 Advisor,是否需要利用动态代理产生一个代理对象。
核心职责:
- 扫描所有Bean定义
- 查找适用于该 Bean 的 Advisor(通知器)
- 如果存在匹配的 Advisor,则创建代理对象替换原 Bean
// BeanPostProcessor 的核心方法
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}Spring AOP 代理的创建过程
当 Spring 容器创建 Bean 时,会经过以下生命周期:
1. 实例化Bean (Instantiation)
2. 属性填充 (Populate)
3. 初始化前 (BeanPostProcessor.postProcessBeforeInitialization)
4. 初始化 (InitializingBean.afterPropertiesSet / @PostConstruct)
5. 初始化后 (BeanPostProcessor.postProcessAfterInitialization) ← 代理创建点
6. 注册到容器InfrastructureAdvisorAutoProxyCreator 在第5步介入,检查是否需要创建代理,以下代码即为完整流程:
// AbstractAutoProxyCreator.wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 1. 检查是否已经处理过
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 2. 检查是否需要跳过
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 3. 判断是否是基础设施类,或者是需要跳过的类型
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 4. 获取适用于该 Bean 的所有 Advisor
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(
bean.getClass(), beanName, null);
// 5. 如果存在匹配的 Advisor 则创建代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 创建代理对象
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors,
new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}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;
}
}::: tipAdvisor 通知器
我们都对 AOP 很熟悉,它的核心就是 切面 和 通知,切面本身就是通过一个 切点 进行切入,通知本质上就是一个 增强。此处 BeanFactoryTransactionAttributeSourceAdvisor 就是一个 切面,它通过 TransactionAttributeSource 这个 切点 进行切入,然后通过 TransactionInterceptor 这个 通知 进行增强。
这也是我们常说de @Transactional 注解实现事务管理的原理就是通过 AOP 实现的。 :::
AnnotationTransactionAttributeSource:事务属性源
主要解析 @Transactional 注解,提取事务属性(传播行为、隔离级别、超时时间等)
public class AnnotationTransactionAttributeSource extends AbstractTransactionAttributeSource {
private final TransactionAnnotationParser annotationParser;
public AnnotationTransactionAttributeSource() {
this.annotationParser = new SpringTransactionAnnotationParser();
}
@Override
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
@Override
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
// 使用注解解析器提取事务属性
return this.annotationParser.parseTransactionAnnotation(element);
}
}BeanFactoryTransactionAttributeSourceAdvisor:事务通知器
将事务属性源和事务拦截器组合在一起,形成一个完整的 Advisor
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
// @Transactional 切点
private final TransactionAttributeSourcePointcut pointcut =
new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}工作流程:
pointcut用于判断方法是否有@Transactional注解- 如果匹配,则应用
TransactionInterceptor通知
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() 方法的执行流程:
- 读取 @Transactional 注解的属性
- 获取事务管理器(TransactionManager)
- 如果需要,创建事务(createTransactionIfNecessary)
- 执行目标方法(proceedWithInvocation)
- 如果正常返回,提交事务(commitTransactionAfterReturning)
- 如果抛出异常,根据回滚规则决定是提交还是回滚(completeTransactionAfterThrowing)
总结
到这里,相信大家已经把 @Transactional 注解的"前世今生"都了解全貌了,下面让我们来回顾一下整个流程:
- 方法上加了
@Transactional注解 - Spring Boot 通过
TransactionAutoConfiguration自动启用了事务管理 @EnableTransactionManagement导入了TransactionManagementConfigurationSelectorTransactionManagementConfigurationSelector导入了ProxyTransactionManagementConfigurationProxyTransactionManagementConfiguration创建了三个核心组件:TransactionAttributeSource(读取注解)TransactionInterceptor(事务拦截器)BeanFactoryTransactionAttributeSourceAdvisor(事务通知器)
- 当调用带有
@Transactional注解的方法时,TransactionInterceptor.invoke()会被调用 invoke()方法调用了父类TransactionAspectSupport.invokeWithinTransaction()方法invokeWithinTransaction这个方法才是事务管理的真正核心!