📝 本文基于 Spring Framework 6.1.4 版本源码分析,
为便于理解,部分源码做了适度简化与伪代码化处理,如需查看完整实现,请参考:
前言
最近写了好几篇关于Spring事务控制的文章,总觉意犹未尽。
于是决定好好来扒一扒@Transactional
的底裤,看看它到底是怎么实现的。
这次来个大招,从源码的角度把整个流程梳理一遍。
从源头开始,到代理对象的创建,再到事务的开启、提交、回滚,每一个环节都不放过。
整篇文章较长,属实费了很多个晚上,熬掉了多少头发,就为了把这个看似简单实则巨复杂的机制盘透彻。
如果你也和我一样好奇,那就一起来看看Spring是如何用一个小小的注解,撑起整个事务管理的吧。
当然,在源码的理解上难免有偏差,如果文章中有错误的地方,还请各位大佬不吝赐教,多多指正。

正文
一切都是代理
很多人觉得@Transactional很神奇,加个注解就能管理事务。其实,这背后的原理并不复杂,核心就是AOP(面向切面编程)。
实际上,Spring 是通过动态代理(JDK 或 CGLIB)来实现事务增强的。你以为调用的是你写的 createUser
方法,其实背后 Spring 替你调用的是代理类的方法。
为了更直观地理解事务的执行流程,我们可以用一段"简化后的伪代码"来展示核心逻辑(该伪代码并不是真实存在的代理类,而是模仿其结构来解释 Spring 内部是如何控制事务的):
代理模式
让我们先来看看最原始的样子:
java
@Service
public class UserService {
@Transactional
public void createUser(User user) {
userRepository.save(user);
// 其他业务逻辑
}
}
当Spring容器启动时,它会发现UserService
里有标注了@Transactional
的方法,于是会创建一个代理对象。这个代理对象大概长这样:
java
// 这是Spring内部生成的代理类(伪代码)
public class UserService$$EnhancerBySpringCGLIB extends UserService {
private TransactionInterceptor transactionInterceptor;
@Override
public void createUser(User user) {
// 开始事务
TransactionInfo txInfo = transactionInterceptor.createTransactionIfNecessary(...);
try {
// 调用原始方法
super.createUser(user);
// 提交事务
transactionInterceptor.commitTransactionAfterReturning(txInfo);
} catch (Exception e) {
// 回滚事务
transactionInterceptor.completeTransactionAfterThrowing(txInfo, e);
throw e;
}
}
}
看到了吗?你以为你调用的是原始的createUser
方法,实际上调用的是代理类的方法。这就是为什么@Transactional
能够工作的根本原因。
两种代理方式:JDK vs CGLIB
Spring支持两种代理方式,选择哪种取决于你的类是否实现了接口。
JDK动态代理:如果你的类实现了接口,Spring会使用JDK动态代理。
java
public interface UserService {
void createUser(User user);
}
@Service
public class UserServiceImpl implements UserService {
@Transactional
public void createUser(User user) {
// 业务逻辑
}
}
CGLIB代理:如果你的类没有实现接口,Spring会使用CGLIB字节码生成技术。
java
@Service
public class UserService { // 没有实现接口
@Transactional
public void createUser(User user) {
// 业务逻辑
}
}
这两种方式各有优劣。JDK动态代理性能更好,但要求必须有接口。CGLIB更灵活,但会有一些限制(比如不能代理final方法)。
有机会的话,后面单独写一篇来讲讲这两种代理。
事务拦截器:划重点
在 Spring 中,TransactionInterceptor
是事务管理的门面类,它实现了 MethodInterceptor
,用于拦截方法调用。
然而它本身并不包含具体的事务执行逻辑,而是将事务的真正处理交给了它的父类:TransactionAspectSupport
。我们可以从它的 invoke(...)
方法看出这一点。
这里为了避免代码篇幅过长,对部分进行删减,尽可能在有限的篇幅中讲清楚原理。
虽然源码有变化,但是对于理解背后的实现并不会造成障碍,甚至会更轻松。
如果你发现这里的源码和实际的源码有差异,莫要惊慌~
java
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 获取目标类
Class<?> targetClass = (invocation.getThis() != null ?
AopUtils.getTargetClass(invocation.getThis()) : null);
// 委托给父类的核心方法处理事务逻辑
return invokeWithinTransaction(invocation.getMethod(), targetClass,
new CoroutinesInvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
}
核心的事务处理逻辑实际上在父类 TransactionAspectSupport
的 invokeWithinTransaction
方法中:
java
// 位于 TransactionAspectSupport 类中
protected Object invokeWithinTransaction(Method method, Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取事务属性
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ?
tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);
// 创建事务信息
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// 执行目标方法
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// 异常处理和回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
// 清理事务信息
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
这段代码里有几个关键点:
- 获取事务属性 :解析
@Transactional
注解的各种配置 - 创建事务:根据传播行为决定是否开启新事务
- 执行业务方法:通过回调机制调用你写的业务逻辑
- 处理结果:根据执行结果决定提交还是回滚
事务提交的内部机制
让我们深入看看commitTransactionAfterReturning
方法是如何工作的:
java
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
// 获取事务管理器并提交
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
这里调用的是PlatformTransactionManager
的commit方法。对于不同的数据源,会有不同的实现。以DataSourceTransactionManager
为例:
java
@Override
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
try {
// 核心:调用JDBC的commit方法
con.commit();
} catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
看到没?最终还是调用了JDBC Connection的commit()
方法,Spring只是在这个基础上做了封装和抽象。
异常回滚的深层逻辑
completeTransactionAfterThrowing
方法更有意思,它需要判断什么情况下回滚:
java
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
// 关键判断:是否需要回滚
if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
try {
// 执行回滚
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
}
} else {
// 即使有异常,但不满足回滚条件,仍然提交
try {
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
} catch (TransactionSystemException ex2) {
ex2.initApplicationException(ex);
throw ex2;
}
}
}
}
这里有个很重要的细节:rollbackOn(ex)
方法的判断逻辑。默认实现(在DefaultTransactionAttribute
)是这样的:
java
@Override
public boolean rollbackOn(Throwable ex) {
return (ex instanceof RuntimeException || ex instanceof Error);
}
这就解释了为什么只有RuntimeException
和Error
会触发回滚。如果是检查型异常,Spring认为这是业务层面的正常流程,不应该回滚事务。
事务状态的生命周期管理
每个事务都有自己的状态信息,Spring通过TransactionStatus
来跟踪:
java
public class DefaultTransactionStatus implements TransactionStatus {
private final Object transaction; // 具体的事务对象(如JDBC Connection)
private final boolean newTransaction; // 是否是新事务(影响提交回滚策略)
private boolean rollbackOnly = false; // 是否只能回滚(一旦标记无法提交)
private boolean completed = false; // 是否已完成(防止重复操作)
private Object savepoint; // 保存点(用于嵌套事务的部分回滚)
// 其他字段和方法...
}
这个状态对象就是事务的身份证,记录了事务的关键信息。
newTransaction
字段要格外注意,它决定了当前方法是否能够提交或回滚事务。如果是false
,那说明当前方法参与的是外层事务,不能擅自处理当前事务。
当TransactionAspectSupport
内部调用createTransactionIfNecessary
时,Spring会创建这个状态对象:
java
protected TransactionInfo createTransactionIfNecessary(
@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// 获取事务状态
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 这里是关键:根据传播行为创建或加入事务
// getTransaction方法会根据@Transactional的propagation属性
// 决定是开启新事务还是加入现有事务
status = tm.getTransaction(txAttr);
}
}
// 准备事务信息并绑定到ThreadLocal
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
这里的getTransaction
方法看起来简单,但内部逻辑相当复杂。
它会检查当前线程是否已经有事务,然后根据传播行为(如REQUIRED
、REQUIRES_NEW
等)决定具体的处理策略。
这里不作展开,后面有机会再来分解。
ThreadLocal:事务信息的载体
Spring使用ThreadLocal
来存储当前线程的事务信息,这样确保了事务的线程安全性:
java
// 静态ThreadLocal,每个线程都有自己的事务信息副本
private static final ThreadLocal<TransactionInfo> transactionInfoHolder =
new NamedThreadLocal<>("Current aspect-driven transaction");
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
// 创建新的事务信息对象
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// 关联事务状态
txInfo.newTransactionStatus(status);
}
// 绑定到当前线程
txInfo.bindToThread();
return txInfo;
}
private void bindToThread() {
// 保存旧的事务信息(用于事务嵌套)
// 这里实现了一个栈结构:新事务信息压栈,旧的暂存
this.oldTransactionInfo = transactionInfoHolder.get();
// 设置当前事务信息为线程的活跃事务
transactionInfoHolder.set(this);
}
这种设计很巧妙,它支持事务的嵌套。当一个事务方法调用另一个事务方法时,新的事务信息会压栈,执行完毕后再出栈恢复之前的事务状态。
就像俄罗斯套娃,外层事务包含内层事务,每层都有自己的状态管理。通过oldTransactionInfo
字段形成的链式结构,Spring可以在方法执行完毕后准确地恢复到上一层的事务状态,确保事务边界的正确性。
@Transactional的生命周期
让我们追踪一下@Transactional
从配置到生效的完整过程。
1. 注解解析
您说得很对!让我补充一下 computeTransactionAttribute
方法的实现,这是整个事务属性解析的核心逻辑:
1. 注解解析:寻找事务的蛛丝马迹(补充完整版)
Spring 使用 AbstractFallbackTransactionAttributeSource
实现了事务属性的缓存和回退策略,之前提到的AnnotationTransactionAttributeSource
就是继承自它:
java
// 父类的核心逻辑
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
// 1. 首先检查缓存
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
return cached;
}
// 2. 计算事务属性,遵循严格的回退策略
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 3. 缓存结果(包括null值,避免重复计算)
this.attributeCache.put(cacheKey, txAttr);
return txAttr;
}
// 这里是事务属性解析的核心算法
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// 只处理public方法(Spring AOP的限制)
if (!Modifier.isPublic(method.getModifiers())) {
return null;
}
// 获取最具体的方法(可能是目标类中重写的方法)
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// 第一优先级:检查目标类中的具体方法
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 第二优先级:检查目标类上的类级别注解
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
// 如果目标类中没有找到,回退到原始方法
if (specificMethod != method) {
// 第三优先级:检查原始方法(通常是接口中的方法)
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 第四优先级:检查原始方法所在类的注解(通常是接口上的注解)
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
}
可以看下这个回退策略的设计,它遵循了"最具体优先"的原则:
优先级顺序(从高到低):
- 实现类的方法 →
@Transactional
直接标注在具体方法上 - 实现类的类 →
@Transactional
标注在实现类上 - 接口的方法 →
@Transactional
标注在接口方法上 - 接口的类 →
@Transactional
标注在接口上
java
// 子类 AnnotationTransactionAttributeSource 的实现
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource {
@Override
protected TransactionAttribute findTransactionAttribute(Method method) {
// 遍历所有注册的事务注解解析器
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(method);
if (attr != null) {
return attr;
}
}
return null;
}
@Override
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
// 遍历所有注册的事务注解解析器
for (TransactionAnnotationParser parser : this.annotationParsers) {
TransactionAttribute attr = parser.parseTransactionAnnotation(clazz);
if (attr != null) {
return attr;
}
}
return null;
}
}
实际的注解解析 由 SpringTransactionAnnotationParser
完成:
java
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser {
@Override
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 查找@Transactional注解
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
// 将注解属性转换为TransactionAttribute对象
return parseTransactionAnnotation(attributes);
}
return null;
}
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 解析传播行为
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
// 解析隔离级别
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
// 解析超时时间
rbta.setTimeout(attributes.getNumber("timeout").intValue());
// 解析只读标志
rbta.setReadOnly(attributes.getBoolean("readOnly"));
// 解析事务管理器限定符
rbta.setQualifier(attributes.getString("value"));
// 解析回滚规则
List<RollbackRule> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRule(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRule(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRule(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRule(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
}
整套设计的几个要点如下:
- 完整的回退策略:确保任何有效的事务配置都不会被遗漏
- 高效的缓存机制:避免重复解析相同的方法
- 灵活的解析器架构:支持不同的事务注解(Spring、JTA、EJB等)
- 最具体优先原则:方法级别的配置总是会覆盖类级别的配置
通过这套机制,Spring 可以准确地为每个方法确定其事务属性,为后续的事务管理提供了坚实的基础。
2. 从@EnableTransactionManagement
到代理创建
@EnableTransactionManagement
负责注册必要的Spring组件来支持注解驱动的事务管理:
java
@EnableTransactionManagement
public class AppConfig {
// 应用配置
}
// @EnableTransactionManagement 内部机制
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// 配置选项
}
// 选择器会根据mode()选择不同的配置类
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:
// AspectJ模式的配置
return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
};
default:
return null;
}
}
}
ProxyTransactionManagementConfiguration
是注册Spring基础设施Bean的配置类:
java
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// 注册事务Advisor(切面)
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource,
TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor =
new BeanFactoryTransactionAttributeSourceAdvisor();
// 设置事务属性源(解析@Transactional注解)
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 设置事务拦截器(实际的事务处理逻辑)
advisor.setAdvice(transactionInterceptor);
return advisor;
}
// 注册事务属性源
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
// 注册事务拦截器
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
return interceptor;
}
}
关键在于 AutoProxyRegistrar
会注册 InfrastructureAdvisorAutoProxyCreator
,这个类负责:
- 扫描所有Bean:寻找带有@Transactional注解的类和方法
- 创建代理:Spring构建动态CGLib代理,可以为你打开和关闭数据库事务
- 织入Advisor :将
BeanFactoryTransactionAttributeSourceAdvisor
织入到代理中
3. 事务执行
当代理方法被调用时,TransactionAspectSupport
会创建事务信息:
java
// TransactionAspectSupport类中的核心方法
protected TransactionInfo createTransactionIfNecessary(
@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr,
final String joinpointIdentification) {
// 如果没有事务属性,直接返回空的TransactionInfo
if (txAttr == null) {
return new TransactionInfo(tm, txAttr, joinpointIdentification);
}
// 如果没有指定名称,使用方法签名作为事务名称
if (txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (tm != null) {
// 这里是关键:根据传播行为创建或加入事务
// getTransaction方法会根据@Transactional的propagation属性
// 决定是开启新事务还是加入现有事务
status = tm.getTransaction(txAttr);
}
// 准备事务信息并绑定到ThreadLocal
// 这个TransactionInfo对象包含了本次事务的所有上下文信息
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
完整的调用链路:
@EnableTransactionManagement
➡️TransactionManagementConfigurationSelector
ProxyTransactionManagementConfiguration
➡️ 注册关键BeanAutoProxyRegistrar
➡️InfrastructureAdvisorAutoProxyCreator
➡️ 创建代理- 方法调用 ➡️
TransactionInterceptor
➡️TransactionAspectSupport
- 创建事务 ➡️ 执行业务逻辑 ➡️ 提交/回滚事务
整个生命周期体现了Spring框架的设计哲学:通过声明式配置简化复杂的事务管理,让开发者专注于业务逻辑而不是底层的事务控制细节。
附录:源码参考文件列表
TransactionInterceptor
TransactionAspectSupport
DefaultTransactionStatus
PlatformTransactionManager
AbstractFallbackTransactionAttributeSource
AnnotationTransactionAttributeSource
SpringTransactionAnnotationParser
BeanFactoryTransactionAttributeSourceAdvisor
ProxyTransactionManagementConfiguration
TransactionManagementConfigurationSelector
EnableTransactionManagement
RuleBasedTransactionAttribute
TransactionAutoConfiguration
总结
写到这里,终于把@Transactional
从头到尾扒了个遍。从一个简单的注解开始,到代理对象的创建,再到事务的开启、提交、回滚,整个过程涉及了Spring框架的多个核心机制。
不得不说,Spring的设计着实精妙,叹为观止。
当然,这篇文章主要是从源码角度来分析,可能有些地方讲得不够深入,有些地方理解得也不够准确。
毕竟Spring的源码博大精深,我这点水平也只是管中窥豹。如果文章中有什么错误或者遗漏的地方,欢迎大家在评论区指正,我会及时修正。
最后,如果这篇文章对你有帮助,不妨点个赞支持一下。如果你对Spring的其他机制也感兴趣,可以关注我,后续会继续分享更多的源码分析文章。
学无止境,我们一起进步!
