1. Spring声明式事务的本质理解
Spring声明式事务是Java企业级开发中最核心的特性之一,它通过简单的注解配置就能实现复杂的事务管理。与编程式事务不同,声明式事务将事务控制从业务代码中抽离,通过AOP(面向切面编程)实现事务边界的动态织入。
在实际项目中,90%的事务异常都源于对声明式事务机制理解不透彻。我曾在一个电商项目中,因为@Transactional注解使用不当导致库存扣减出现并发问题,这个教训让我深刻认识到理解源码的重要性。
2. 事务核心接口体系解析
2.1 PlatformTransactionManager架构
Spring事务抽象的核心是PlatformTransactionManager接口,它定义了三个关键方法:
java复制public interface PlatformTransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition);
void commit(TransactionStatus status);
void rollback(TransactionStatus status);
}
常见实现类包括:
- DataSourceTransactionManager:JDBC单数据源事务
- JpaTransactionManager:JPA持久化事务
- JtaTransactionManager:分布式事务
重要提示:事务管理器选择必须与持久层技术匹配,混合使用会导致事务失效
2.2 事务定义与状态对象
TransactionDefinition定义了事务七大属性:
- 传播行为(PROPAGATION_REQUIRED等)
- 隔离级别(ISOLATION_DEFAULT等)
- 超时时间(默认-1)
- 是否只读
- 事务名称
- 回滚规则
- 事务同步方式
TransactionStatus则包含事务运行时状态:
java复制public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
3. @Transactional注解实现原理
3.1 注解属性与事务定义映射
Spring通过TransactionAttributeSource将注解属性转换为TransactionDefinition:
java复制public interface TransactionAttributeSource {
TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass);
}
典型属性映射关系:
| 注解属性 | 事务定义属性 |
|---|---|
| propagation | propagationBehavior |
| isolation | isolationLevel |
| timeout | timeout |
| readOnly | readOnly |
| rollbackFor | rollbackRules |
3.2 代理对象生成机制
Spring通过AOP代理实现事务增强,核心流程:
- 在Bean初始化后置处理中,AbstractAutoProxyCreator识别@Transactional注解
- 创建代理对象时,根据代理工厂配置选择JDK动态代理或CGLIB
- 将TransactionInterceptor加入拦截器链
踩坑记录:自调用问题就是因为代理对象调用内部方法不会经过拦截器链
4. 事务执行全流程剖析
4.1 事务拦截器工作流程
TransactionInterceptor的invoke方法核心逻辑:
java复制public Object invoke(MethodInvocation invocation) {
// 1. 获取事务属性
TransactionAttribute txAttr = getTransactionAttributeSource()
.getTransactionAttribute(invocation.getMethod(), targetClass);
// 2. 获取事务管理器
PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 3. 开启事务
TransactionStatus status = tm.getTransaction(txAttr);
try {
// 4. 执行业务方法
Object result = invocation.proceed();
// 5. 提交事务
tm.commit(status);
return result;
} catch (Exception ex) {
// 6. 异常回滚处理
completeTransactionAfterThrowing(txAttr, status, ex);
throw ex;
}
}
4.2 事务同步机制详解
TransactionSynchronizationManager通过ThreadLocal实现资源绑定:
java复制// 关键ThreadLocal变量
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
典型应用场景:
- 同一事务内获取相同Connection
- 事务事件回调(afterCommit等)
- Hibernate Session绑定
5. 传播行为源码实现
5.1 七种传播行为解析
Spring定义了七种传播行为,核心实现位于AbstractPlatformTransactionManager:
java复制// REQUIRED传播行为实现逻辑
if (isExistingTransaction(transaction)) {
// 存在事务:加入当前事务
return prepareTransactionStatus(
definition, transaction, false, newSynchronization, debugEnabled, null);
} else {
// 无事务:新建事务
return startTransaction(definition, transaction, debugEnabled, suspendedResources);
}
5.2 嵌套事务实现原理
NESTED传播使用Savepoint机制实现:
java复制// DataSourceTransactionManager实现
@Override
protected Object doCreateSavepoint() throws TransactionException {
ConnectionHolder conHolder = getConnectionHolder();
return conHolder.createSavepoint();
}
实战经验:NESTED只适用于JDBC,JPA等实现可能不支持
6. 事务失效场景深度分析
6.1 典型失效场景排查
- 自调用问题(最常见)
- 异常类型不匹配(默认只回滚RuntimeException)
- 方法修饰符非public
- 多线程环境下ThreadLocal失效
- 数据库引擎不支持事务(如MyISAM)
6.2 源码级解决方案
针对自调用问题,可通过AopContext获取当前代理:
java复制@Transactional
public void outerMethod() {
// 错误方式
innerMethod();
// 正确方式
((YourService)AopContext.currentProxy()).innerMethod();
}
7. 高级定制与扩展
7.1 自定义事务管理器
扩展AbstractPlatformTransactionManager示例:
java复制public class CustomTxManager extends AbstractPlatformTransactionManager {
@Override
protected Object doGetTransaction() {
// 实现事务对象获取
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
// 实现事务开始逻辑
}
@Override
protected void doCommit(DefaultTransactionStatus status) {
// 实现提交逻辑
}
}
7.2 事务事件监听
实现TransactionSynchronization接口:
java复制TransactionSynchronizationManager.registerSynchronization(
new TransactionSynchronization() {
@Override
public void afterCommit() {
// 事务提交后处理
}
});
经过对Spring事务源码的完整分析,最大的体会是:理解事务传播行为的关键在于掌握ThreadLocal的使用,而事务失效的排查需要结合代理机制和AOP原理。在实际项目中,建议通过调试TransactionInterceptor来验证事务配置是否符合预期