1. 为什么需要深入理解Spring声明式事务源码
作为一名Java开发者,我最初接触Spring事务时,只是简单地在方法上添加@Transactional注解就认为万事大吉。直到某次线上事故——一个本该回滚的操作却提交了数据,导致业务数据不一致——我才意识到,仅仅会使用API是远远不够的。
Spring声明式事务看似简单,实则内部机制复杂精妙。通过源码学习,我们可以:
- 准确理解事务的传播行为和隔离级别的实际表现
- 定位和解决事务失效、不回滚等疑难问题
- 根据业务需求定制特殊的事务行为
- 在面试中展现对Spring框架的深度理解
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Spring事务的核心架构设计
2.1 事务管理器的抽象与实现
Spring事务的核心接口是PlatformTransactionManager,它定义了三个关键方法:
java复制public interface PlatformTransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}
常见实现类包括:
- DataSourceTransactionManager:用于JDBC和MyBatis
- HibernateTransactionManager:用于Hibernate
- JpaTransactionManager:用于JPA
提示:在Spring Boot中,当我们引入spring-boot-starter-jdbc依赖时,会自动配置DataSourceTransactionManager
2.2 事务定义的标准化
TransactionDefinition接口定义了事务的七大属性:
- 传播行为(PROPAGATION_REQUIRED等)
- 隔离级别(ISOLATION_DEFAULT等)
- 超时时间
- 是否只读
- 事务名称
- 回滚规则(哪些异常触发回滚)
- 事务同步(如Connection的绑定与解绑)
3. @Transactional注解的解析过程
3.1 注解的元数据解析
Spring通过TransactionAttributeSource接口解析@Transactional注解:
java复制public interface TransactionAttributeSource {
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
}
默认实现是AnnotationTransactionAttributeSource,它会读取注解中的:
- propagation:传播行为
- isolation:隔离级别
- timeout:超时时间
- readOnly:是否只读
- rollbackFor/rollbackForClassName/noRollbackFor/noRollbackForClassName:回滚规则
3.2 代理对象的创建
Spring通过AOP为被@Transactional注解的类创建代理对象。关键类包括:
- AbstractAutoProxyCreator:自动代理创建器
- TransactionInterceptor:事务拦截器
- ProxyFactory:代理工厂
创建过程:
- 扫描所有Bean定义
- 检查是否有@Transactional注解
- 为符合条件的Bean创建代理
- 将TransactionInterceptor加入拦截器链
4. 事务执行的完整流程
4.1 事务的开启与获取
当调用代理方法时,TransactionInterceptor会:
- 获取TransactionManager
- 根据@Transactional配置创建TransactionDefinition
- 调用TransactionManager.getTransaction()开启事务
关键代码路径:
code复制TransactionInterceptor.invoke()
-> TransactionAspectSupport.invokeWithinTransaction()
-> AbstractPlatformTransactionManager.getTransaction()
4.2 事务的提交与回滚
方法执行完成后,TransactionInterceptor会根据执行结果决定提交或回滚:
java复制try {
retVal = invocation.proceedWithInvocation();
completeTransactionAfterReturning(txInfo, retVal);
return retVal;
} catch (Throwable ex) {
completeTransactionAfterReturning(txInfo, ex);
throw ex;
}
注意:默认只对RuntimeException和Error回滚,检查异常不会触发回滚
5. 事务传播行为的实现原理
5.1 PROPAGATION_REQUIRED的实现
这是最常用的传播行为,实现逻辑:
- 如果当前没有事务,就新建一个事务
- 如果已经存在事务,就加入该事务
关键代码在AbstractPlatformTransactionManager.handleExistingTransaction():
java复制if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED) {
if (isExistingTransaction(transaction)) {
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
}
5.2 PROPAGATION_REQUIRES_NEW的实现
总是新建事务,如果当前存在事务,则挂起当前事务:
java复制SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
} catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
挂起的事务信息保存在ThreadLocal中,新事务完成后会恢复。
6. 事务同步与资源管理
6.1 连接资源的绑定与解绑
Spring通过TransactionSynchronizationManager管理事务资源:
java复制public abstract class TransactionSynchronizationManager {
private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
// ...
}
DataSourceUtils.getConnection()会从当前事务获取连接,而不是直接创建新连接。
6.2 事务同步回调
可以实现TransactionSynchronization接口在事务完成前后执行自定义逻辑:
java复制TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务提交后执行
}
});
7. 常见问题与解决方案
7.1 事务失效的常见原因
- 方法不是public的
- 自调用(同一个类中方法A调用方法B)
- 异常被捕获未抛出
- 异常类型不是RuntimeException
- 数据库引擎不支持事务(如MyISAM)
7.2 排查事务问题的技巧
- 开启Spring事务调试日志:
properties复制logging.level.org.springframework.transaction=DEBUG
- 检查代理对象:
java复制System.out.println(bean.getClass()); // 应该输出代理类名
- 使用TransactionSynchronizationManager判断当前是否有事务:
java复制boolean active = TransactionSynchronizationManager.isActualTransactionActive();
8. 高级应用与扩展
8.1 自定义事务管理器
可以继承AbstractPlatformTransactionManager实现特殊的事务管理需求,比如:
- 分布式事务
- 多数据源事务
- 特殊资源的事务管理
8.2 编程式事务与声明式事务结合
在某些复杂场景下,可以混合使用:
java复制@Transactional
public void businessMethod() {
// 声明式事务
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.execute(status -> {
// 编程式事务
return null;
});
}
8.3 事务事件监听
Spring 4.2+支持事务事件监听:
java复制@Component
public class MyTransactionListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(MyEvent event) {
// 事务提交后处理
}
}
9. 性能优化建议
- 合理设置事务超时时间,避免长时间占用连接
- 只读查询标记为readOnly=true
- 避免在事务中进行远程调用
- 大事务拆分为小事务
- 合理选择隔离级别,READ_COMMITTED通常足够
10. 源码阅读路线图
建议按以下顺序阅读关键源码:
- @Transactional注解定义
- TransactionAttributeSource及其实现
- TransactionInterceptor
- AbstractPlatformTransactionManager
- DataSourceTransactionManager
- TransactionSynchronizationManager
- TransactionAspectSupport
我在实际阅读源码时发现,结合具体问题(如"为什么这个方法的事务没生效")去追踪代码路径,比单纯从头到尾阅读更有效。另外,合理使用IDE的调用层级(Call Hierarchy)功能可以快速理清调用关系。
