广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Spring事务的开启原理详解
  • 533
分享到

Spring事务的开启原理详解

2024-04-02 19:04:59 533人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录@EnableTransactionManagement开启事务原理解析总结 在事务配置类上声明@EnableTransactionManagement注解开启事务 在事

  1. 在事务配置类上声明@EnableTransactionManagement注解开启事务
  2. 在事务配置类上定义数据源
  3. 在事务配置类上定义事务管理器
  4. 在相关类或者方法上使用@Transactional声明事务

代码如下:


@Configuration
@EnableTransactionManagement
public class RootConfig{
 
 @Bean
 public DataSource dataSource(){
  DruidDataSource dataSource = new DruidDataSource();
  dataSource.setXXX();
  ...
  
  return dataSource;
 }
 
 @Bean
 public PlatfromTransactionManager txManager(){
  return new DataSourceTransactionManager(dataSource());
 }
}

@Service
public class UserService{

 @Autowired
 private UserRepository userRepository;
 
 @Transactional
 public void addUser(User user){
  userRepository.save(user);
 }
}

@EnableTransactionManagement开启事务原理解析

@EnableTransactionManagement源码如下:


@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
 boolean proxyTargetClass() default false;
 AdviceMode mode() default AdviceMode.PROXY;
 int order() default Ordered.LOWEST_PRECEDENCE;
}

可以看到,@EnableTransactionManagement接口类主要Import了TransactionManagementConfigurationSelector来实现其注入,而TransactionManagementConfigurationSelector又主要使用selectImport方法来实现其注入,代码如下:


@Override
public final String[] selectImports(AnnotationMetadata importinGClaSSMetadata) {
 Class<?> annoType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
 AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
 if (attributes == null) {
  throw new IllegalArgumentException(String.fORMat(
   "@%s is not present on importing class '%s' as expected",
   annoType.getSimpleName(), importingClassMetadata.getClassName()));
 }

 AdviceMode adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
 //根据AdviceMode返回不同的类型,默认是AdviceMode.PROXY。
 String[] imports = selectImports(adviceMode);
 if (imports == null) {
  throw new IllegalArgumentException(String.format("Unknown AdviceMode: '%s'", adviceMode));
 }
 return imports;
}

@Override
protected String[] selectImports(AdviceMode adviceMode) {
 switch (adviceMode) {
  case PROXY:
   return new String[] {AutoProxyReGIStrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
  case ASPECTJ:
   return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
  default:
   return null;
 }
}

其中主要功能点为根据AdviceMode选择创建不同的bean,AdviceMode的默认代理方式是PROXY,jdk代理。所以返回的是AutoProxyRegistrar和ProxyTransactionManagementConfiguration。

我们先分析AutoProxyRegistrar,AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,那在创建bean的时候会调用registerBeanDefinitions方法。registerBeanDefinitions方法的实现:


@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
 boolean candidateFound = false;
 Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
 for (String annoType : annoTypes) {
  AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
  if (candidate == null) {
   continue;
  }
  Object mode = candidate.get("mode");
  Object proxyTargetClass = candidate.get("proxyTargetClass");
  if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
    Boolean.class == proxyTargetClass.getClass()) {
   candidateFound = true;
   //只有@EnableTransactionManagement注解才会走到这里
   if (mode == AdviceMode.PROXY) {
    aopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
    if ((Boolean) proxyTargetClass) {
     AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     return;
    }
   }
  }
 }
 //...
}

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
 return registerOrEScalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

可以看到,它通过注册InfrastructureAdvisorAutoProxyCreator来启动spring Aop。

接下来再看ProxyTransactionManagementConfiguration的作用,代码如下:


@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

 @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
  BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
  advisor.setTransactionAttributeSource(transactionAttributeSource());
  advisor.setAdvice(transactionInterceptor());
  advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
  return advisor;
 }

 @Bean
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 public TransactionAttributeSource transactionAttributeSource() {
  return new AnnotationTransactionAttributeSource();
 }

 @Bean
 @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 public TransactionInterceptor transactionInterceptor() {
  TransactionInterceptor interceptor = new TransactionInterceptor();
  interceptor.setTransactionAttributeSource(transactionAttributeSource());
  if (this.txManager != null) {
   interceptor.setTransactionManager(this.txManager);
  }
  return interceptor;
 }

}

ProxyTransactionManagementConfiguration是一个配置文件,注册了三个bean,BeanFactoryTransactionAttributeSourceAdvisor、AnnotationTransactionAttributeSource、TransactionInterceptor,而这三个类分别继承Advisor、Advice和Pointcut。即切面所需组件。

总结

@EnableTransactionManagement利用AutoProxyRegistrar启动Spring Aop,使用ProxyTransactionManagementConfiguration配置对应切面部件。

以上就是Spring事务的简单实现步骤的详细内容,更多关于Spring事务实现步骤的资料请关注编程网其它相关文章!

--结束END--

本文标题: Spring事务的开启原理详解

本文链接: https://www.lsjlt.com/news/122155.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作