好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring事务的开启原理详解

在事务配置类上声明@EnableTransactionManagement注解开启事务 在事务配置类上定义数据源 在事务配置类上定义事务管理器 在相关类或者方法上使用@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事务的开启原理详解的详细内容...

  阅读:15次