gpt4 book ai didi

Spring事务的开启原理详解

转载 作者:qq735679552 更新时间:2022-09-29 22:32:09 33 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章Spring事务的开启原理详解由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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());
  }
}
?
1
2
3
4
5
6
7
8
9
10
11
@Service
public class UserService{
 
  @Autowired
  private UserRepository userRepository;
 
  @Transactional
  public void addUser(User user){
   userRepository.save(user);
  }
}

@EnableTransactionManagement开启事务原理解析

@EnableTransactionManagement源码如下:

?
1
2
3
4
5
6
7
8
9
@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方法来实现其注入,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@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方法的实现:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@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的作用,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@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事务实现步骤的资料请关注我其它相关文章! 。

原文链接:https://segmentfault.com/a/1190000039354542 。

最后此篇关于Spring事务的开启原理详解的文章就讲到这里了,如果你想了解更多关于Spring事务的开启原理详解的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com