当前位置:   article > 正文

Spring源码:声明式事务@Transactional源码分析--spring boot方式_spring boot声明式事务源码解读

spring boot声明式事务源码解读

目录

1. TransactionAutoConfiguration

2. @EnableTransactionManagement

3. TransactionManagementConfigurationSelector

3.1 AutoProxyRegistrar

3.2 ProxyTransactionManagementConfiguration

3.2.1 ProxyTransactionManagementConfiguration

3.2.2 AbstractTransactionManagementConfiguration


spring boot提供的一个很好的特性就是自动配置,能够省去很多手动配置带来的烦恼,大大提升项目的开发效率;这里spring对声明式事务的支持也从自动配置说起,spring对声明式事务的原生xml支持请移步:Spring源码:声明式事务@Transactional源码分析--spring xml实现

1. TransactionAutoConfiguration

  1. /**
  2. * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration
  3. * Auto-configuration} for Spring transaction.
  4. *
  5. * @author Stephane Nicoll
  6. * @since 1.3.0
  7. */
  8. @Configuration
  9. @ConditionalOnClass(PlatformTransactionManager.class)
  10. @AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
  11. DataSourceTransactionManagerAutoConfiguration.class,
  12. Neo4jDataAutoConfiguration.class })
  13. @EnableConfigurationProperties(TransactionProperties.class)
  14. public class TransactionAutoConfiguration {
  15. @Bean
  16. @ConditionalOnMissingBean
  17. public TransactionManagerCustomizers platformTransactionManagerCustomizers(
  18. ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {
  19. return new TransactionManagerCustomizers(customizers.getIfAvailable());
  20. }
  21. @Configuration
  22. @ConditionalOnSingleCandidate(PlatformTransactionManager.class)
  23. public static class TransactionTemplateConfiguration {
  24. private final PlatformTransactionManager transactionManager;
  25. public TransactionTemplateConfiguration(
  26. PlatformTransactionManager transactionManager) {
  27. this.transactionManager = transactionManager;
  28. }
  29. @Bean
  30. @ConditionalOnMissingBean
  31. public TransactionTemplate transactionTemplate() {
  32. return new TransactionTemplate(this.transactionManager);
  33. }
  34. }
  35. @Configuration
  36. @ConditionalOnBean(PlatformTransactionManager.class)
  37. @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
  38. public static class EnableTransactionManagementConfiguration {
  39. @Configuration
  40. @EnableTransactionManagement(proxyTargetClass = false)
  41. @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
  42. public static class JdkDynamicAutoProxyConfiguration {
  43. }
  44. @Configuration
  45. @EnableTransactionManagement(proxyTargetClass = true)
  46. @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
  47. public static class CglibAutoProxyConfiguration {
  48. }
  49. }
  50. }

由于在使用spring事务管理时,spring.aop.proxy-target-class默认为true,所以CglibAutoProxyConfiguration会生效,下面分析一下@EnableTransactionManagement的处理逻辑

2. @EnableTransactionManagement

EnableTransactionManagement主要定义了声明式事务代理目标类的方式、增强模式以及优先级,同时通过@Import注解导入了TransactionManagementConfigurationSelector implement ImportSelector,见如下源码,下面对TransactionManagementConfigurationSelector进行分析;

  1. @Target(ElementType.TYPE)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. @Import(TransactionManagementConfigurationSelector.class)
  5. public @interface EnableTransactionManagement {
  6. /**
  7. * Indicate whether subclass-based (CGLIB) proxies are to be created ({@code true}) as
  8. * opposed to standard Java interface-based proxies ({@code false}). The default is
  9. * {@code false}. <strong>Applicable only if {@link #mode()} is set to
  10. * {@link AdviceMode#PROXY}</strong>.
  11. * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
  12. * Spring-managed beans requiring proxying, not just those marked with
  13. * {@code @Transactional}. For example, other beans marked with Spring's
  14. * {@code @Async} annotation will be upgraded to subclass proxying at the same
  15. * time. This approach has no negative impact in practice unless one is explicitly
  16. * expecting one type of proxy vs another, e.g. in tests.
  17. */
  18. boolean proxyTargetClass() default false;
  19. /**
  20. * Indicate how transactional advice should be applied.
  21. * <p><b>The default is {@link AdviceMode#PROXY}.</b>
  22. * Please note that proxy mode allows for interception of calls through the proxy
  23. * only. Local calls within the same class cannot get intercepted that way; an
  24. * {@link Transactional} annotation on such a method within a local call will be
  25. * ignored since Spring's interceptor does not even kick in for such a runtime
  26. * scenario. For a more advanced mode of interception, consider switching this to
  27. * {@link AdviceMode#ASPECTJ}.
  28. */
  29. AdviceMode mode() default AdviceMode.PROXY;
  30. /**
  31. * Indicate the ordering of the execution of the transaction advisor
  32. * when multiple advices are applied at a specific joinpoint.
  33. * <p>The default is {@link Ordered#LOWEST_PRECEDENCE}.
  34. */
  35. int order() default Ordered.LOWEST_PRECEDENCE;
  36. }

3. TransactionManagementConfigurationSelector

其继承结构如下图:

可以看出TransactionManagementConfigurationSelector本质上是一个ImportSelector,具体导入了哪些类,通过如下代码可以看出,在采用AdviceMode.PROXY时,导入了AutoProxyRegistrar和ProxyTransactionManagementConfiguration,下面分别对这两个类进行分析;

  1. /**
  2. * Selects which implementation of {@link AbstractTransactionManagementConfiguration}
  3. * should be used based on the value of {@link EnableTransactionManagement#mode} on the
  4. * importing {@code @Configuration} class.
  5. *
  6. * @author Chris Beams
  7. * @since 3.1
  8. * @see EnableTransactionManagement
  9. * @see ProxyTransactionManagementConfiguration
  10. * @see TransactionManagementConfigUtils#TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME
  11. */
  12. public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  13. /**
  14. * {@inheritDoc}
  15. * @return {@link ProxyTransactionManagementConfiguration} or
  16. * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
  17. * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
  18. */
  19. @Override
  20. protected String[] selectImports(AdviceMode adviceMode) {
  21. switch (adviceMode) {
  22. case PROXY:
  23. return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
  24. case ASPECTJ:
  25. return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
  26. default:
  27. return null;
  28. }
  29. }
  30. }

3.1 AutoProxyRegistrar

AutoProxyRegistrar的具体实现如下,通过AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry)的方式注册了beandefinition:InfrastructureAdvisorAutoProxyCreator,和spring xml声明式事务导入了同样的自动代理创建类,完成代理的创建过程;

  1. /**
  2. * Registers an auto proxy creator against the current {@link BeanDefinitionRegistry}
  3. * as appropriate based on an {@code @Enable*} annotation having {@code mode} and
  4. * {@code proxyTargetClass} attributes set to the correct values.
  5. *
  6. * @author Chris Beams
  7. * @since 3.1
  8. * @see EnableAspectJAutoProxy
  9. */
  10. public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  11. private final Log logger = LogFactory.getLog(getClass());
  12. /**
  13. * Register, escalate, and configure the standard auto proxy creator (APC) against the
  14. * given registry. Works by finding the nearest annotation declared on the importing
  15. * {@code @Configuration} class that has both {@code mode} and {@code proxyTargetClass}
  16. * attributes. If {@code mode} is set to {@code PROXY}, the APC is registered; if
  17. * {@code proxyTargetClass} is set to {@code true}, then the APC is forced to use
  18. * subclass (CGLIB) proxying.
  19. * <p>Several {@code @Enable*} annotations expose both {@code mode} and
  20. * {@code proxyTargetClass} attributes. It is important to note that most of these
  21. * capabilities end up sharing a {@linkplain AopConfigUtils#AUTO_PROXY_CREATOR_BEAN_NAME
  22. * single APC}. For this reason, this implementation doesn't "care" exactly which
  23. * annotation it finds -- as long as it exposes the right {@code mode} and
  24. * {@code proxyTargetClass} attributes, the APC can be registered and configured all
  25. * the same.
  26. */
  27. @Override
  28. public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
  29. boolean candidateFound = false;
  30. Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
  31. for (String annoType : annoTypes) {
  32. AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
  33. if (candidate == null) {
  34. continue;
  35. }
  36. Object mode = candidate.get("mode");
  37. Object proxyTargetClass = candidate.get("proxyTargetClass");
  38. if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
  39. Boolean.class == proxyTargetClass.getClass()) {
  40. candidateFound = true;
  41. if (mode == AdviceMode.PROXY) {
  42. AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
  43. if ((Boolean) proxyTargetClass) {
  44. AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
  45. return;
  46. }
  47. }
  48. }
  49. }
  50. if (!candidateFound) {
  51. String name = getClass().getSimpleName();
  52. logger.warn(String.format("%s was imported but no annotations were found " +
  53. "having both 'mode' and 'proxyTargetClass' attributes of type " +
  54. "AdviceMode and boolean respectively. This means that auto proxy " +
  55. "creator registration and configuration may not have occurred as " +
  56. "intended, and components may not be proxied as expected. Check to " +
  57. "ensure that %s has been @Import'ed on the same class where these " +
  58. "annotations are declared; otherwise remove the import of %s " +
  59. "altogether.", name, name, name));
  60. }
  61. }
  62. }

3.2 ProxyTransactionManagementConfiguration

继承结构如下:

下面分别对ProxyTransactionManagementConfiguration和AbstractTransactionManagementConfiguration进行说明;

3.2.1 ProxyTransactionManagementConfiguration

源码如下,可见该类是一个Configuration类,完成了如下3个bean的定义:

  • AnnotationTransactionAttributeSource
  • TransactionInterceptor
  • BeanFactoryTransactionAttributeSourceAdvisor

这和spring xml声明式事务的定义完全一致;

  1. /**
  2. * {@code @Configuration} class that registers the Spring infrastructure beans
  3. * necessary to enable proxy-based annotation-driven transaction management.
  4. *
  5. * @author Chris Beams
  6. * @since 3.1
  7. * @see EnableTransactionManagement
  8. * @see TransactionManagementConfigurationSelector
  9. */
  10. @Configuration
  11. public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
  12. @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
  13. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  14. public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
  15. BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
  16. advisor.setTransactionAttributeSource(transactionAttributeSource());
  17. advisor.setAdvice(transactionInterceptor());
  18. advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
  19. return advisor;
  20. }
  21. @Bean
  22. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  23. public TransactionAttributeSource transactionAttributeSource() {
  24. return new AnnotationTransactionAttributeSource();
  25. }
  26. @Bean
  27. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  28. public TransactionInterceptor transactionInterceptor() {
  29. TransactionInterceptor interceptor = new TransactionInterceptor();
  30. interceptor.setTransactionAttributeSource(transactionAttributeSource());
  31. if (this.txManager != null) {
  32. interceptor.setTransactionManager(this.txManager);
  33. }
  34. return interceptor;
  35. }
  36. }

3.2.2 AbstractTransactionManagementConfiguration

AbstractTransactionManagementConfiguration主要完成了@EnableTransactionManagement注解属性的解析,同时通过注入TransactionManagementConfigurer类型的bean,完成事务管理器PlatformTransactionManager的设置,如下:

  1. /**
  2. * Abstract base {@code @Configuration} class providing common structure for enabling
  3. * Spring's annotation-driven transaction management capability.
  4. *
  5. * @author Chris Beams
  6. * @author Stephane Nicoll
  7. * @since 3.1
  8. * @see EnableTransactionManagement
  9. */
  10. @Configuration
  11. public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
  12. protected AnnotationAttributes enableTx;
  13. /**
  14. * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
  15. */
  16. protected PlatformTransactionManager txManager;
  17. @Override
  18. public void setImportMetadata(AnnotationMetadata importMetadata) {
  19. this.enableTx = AnnotationAttributes.fromMap(
  20. importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
  21. if (this.enableTx == null) {
  22. throw new IllegalArgumentException(
  23. "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
  24. }
  25. }
  26. @Autowired(required = false)
  27. void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
  28. if (CollectionUtils.isEmpty(configurers)) {
  29. return;
  30. }
  31. if (configurers.size() > 1) {
  32. throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
  33. }
  34. TransactionManagementConfigurer configurer = configurers.iterator().next();
  35. this.txManager = configurer.annotationDrivenTransactionManager();
  36. }
  37. @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
  38. @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  39. public TransactionalEventListenerFactory transactionalEventListenerFactory() {
  40. return new TransactionalEventListenerFactory();
  41. }
  42. }

综上,spring声明式事务xml配置形式和spring boot自动配置形式完全一致,均完成了对spring声明式事务的支持;

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/525700
推荐阅读
相关标签
  

闽ICP备14008679号