在Spring框架中,事务管理是一个重要的功能,它可以确保在数据库操作过程中的一致性和完整性。Spring提供了多种方式来实现事务管理,其中基于注解的方式是一种简洁而方便的选择。本文将深入探讨Spring源码中基于注解的事务管理的实现原理。
Srping事务使用
事务是一组操作的集合,这些操作要么全部成功执行,要么全部回滚到初始状态。事务管理是指在应用程序中对数据库操作进行管理,确保事务的一致性和隔离性。
下面我们来看一段Spring事务在我们平时开发中的应用
// 开启Spring事务,通过注解@EnableTransactionManagement
@Configuration
@ComponentScan(basePackages = {"com.gu"})
@EnableTransactionManagement
public class MainConfig {
...
}
// 在具体类或方法上添加注解@Transactional
@Service
public class ReimburseService {
@Autowired
private ExpenseServiceRepository expenseServiceRepository;
@Transactional
public void function1(Reimburse reimburse){
// 保存报销单
reimburseRepository.save(reimburse);
// 保存费用
expenseServiceRepository.save(reimburse.getExpense());
}
}
@Service
public class ExpenseService {
@Transactional
public void function2(Expense expense){
// 保存费用
expenseServiceRepository.save(expense);
}
}
上述例子主要关注两个注解@Transactional和@EnableTransactionManagement
- @EnableTransactionManagement
用于启用Spring的事务管理功能。通常在配置类上使用- @Transactional
用于标记需要进行事务管理的方法或类。可以在方法上或类上使用,表示该方法或类需要在事务中执行
Spring事务准备
@EnableTransactionManagement
现在来看注解@EnableTransactionManagement ,可以看到该注解实际上就是会自动注册TransactionManagementConfigurationSelector作为配置类的一个组件.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
...
}
接着来看TransactionManagementConfigurationSelector
// 实际就是在spring容器里增加了两个bean
// AutoProxyRegistrar 和 ProxyTransactionManagementConfiguration
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
AutoProxyRegistrar
AutoProxyRegistrar的主要作用是开启AOP.
向Spring容器中注册了一个 InfrastructureAdvisorAutoProxyCreator的Bean. 而InfrastructureAdvisorAutoProxyCreator 继承了AbstractAdvisorAutoProxyCreator,所以这个类的主要作用就是开启自动代理的作用,也就是一个BeanPostProcessor,会在初始化后步骤中去寻找Advisor类型的Bean,并判断当前某个 Bean是否有匹配的Advisor,是否需要利用动态代理产生一个代理对象。
// 向Spring容器中注册了一个 InfrastructureAdvisorAutoProxyCreator
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
// ->
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
ProxyTransactionManagementConfiguration
是一个配置类,里面定义了3个Bean
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
/**
* 创建一个事务切面(就是一个BeanPostProcess)
* 一个advisor,需要TransactionAttributeSource + TransactionInterceptor构造
* @param transactionAttributeSource
* @param transactionInterceptor
* @return
*/
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
// 创建BeanFactoryTransactionAttributeSourceAdvisor对象作为事务切面
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 设置事务属性源
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 设置事务拦截器
advisor.setAdvice(transactionInterceptor);
// 设置切面的顺序
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// 是个工具类,相当于pointcut,用来判断@Transactional
return new AnnotationTransactionAttributeSource();
}
/**
* 创建一个事务拦截器
* 相当于advice,是代理逻辑,当某个类中存在@Transactional注解时,到时就产生一个代理对象作为Bean,
* 代理对象在执行某个方法时,最终就会进入到TransactionInterceptor的 invoke()方法。
* @param transactionAttributeSource
* @return
*/
@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;
}
}