Spring 事务
Spring 提供声明式事务管理,通过 @Transactional 注解简化事务处理。
配置方式
XML 配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>注解配置
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dataSource());
}
}解析机制
入口在 TxNamespaceHandler → AnnotationDrivenBeanDefinitionParser.parse:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
registerTransactionalEventListenerFactory(parserContext);
String mode = element.getAttribute("mode");
if ("aspectj".equals(mode)) {
registerTransactionAspect(element, parserContext);
} else {
// mode="proxy"(默认)
AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
}
return null;
}configureAutoProxyCreator 注册核心组件链:
BeanFactoryTransactionAttributeSourceAdvisor → TransactionInterceptor → AnnotationTransactionAttributeSource代理类生成
InfrastructureAdvisorAutoProxyCreator 只考虑 Spring 内部基础设施 Advisor。
// AbstractAutoProxyCreator.postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}findEligibleAdvisors 寻找适合当前 Bean 的 Advisor:
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
}事务运行流程
事务传播行为
| 传播行为 | 说明 |
|---|---|
| REQUIRED | 支持当前事务,没有则创建新事务(默认) |
| REQUIRES_NEW | 挂起当前事务,创建新事务 |
| NESTED | 嵌套事务(Savepoint) |
| SUPPORTS | 支持当前事务 |
| NOT_SUPPORTED | 挂起当前事务 |
| MANDATORY | 必须有当前事务 |
| NEVER | 不能有事务 |
嵌套事务(NESTED)
使用 JDBC Savepoint 实现:
Connection con = DataSourceUtils.getConnection(dataSource);
con.setSavepoint();
// 嵌套事务失败时回滚到 Savepoint
con.rollback(savepoint);@Transactional 注解属性
| 属性 | 说明 |
|---|---|
| propagation | 传播行为 |
| isolation | 隔离级别 |
| readOnly | 是否只读 |
| timeout | 超时时间 |
| rollbackFor | 回滚异常类型 |
| noRollbackFor | 不回滚异常类型 |
注意
失效场景
@Transactional修饰非 public 方法- 同一类内部方法调用(绕过代理)
- 异常被 catch 吞掉
- 异常类型不匹配