- 在事务配置类上声明@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