の@Transactional Springbootソースコード解析

要約:

SpringBoot理解する方法を、実際に、それは上のあなたを見ているSpring Frameworkような-どのように身近なSpringBoot実際には春のフレームワークを提供する能力に属しモジュールアセンブリの設計モデルの数が多いです、。基づいて、今日SpringBoot人気のあるXML過去の春Frameworkの構成運命のものを使用します。注釈駆動型アプリケーション指向プログラミングのメタデータはすでに、より多くの開発者のための好みの対象となり、結局、それは便利度だ、XMLの利点は、比類のない方法です。

    @Configuration
    @ConditionalOnClass({PlatformTransactionManager.class})
    @AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
    @EnableConfigurationProperties({TransactionProperties.class})
    public class TransactionAutoConfiguration {
        public TransactionAutoConfiguration() {
        }
    
        @Bean
        @ConditionalOnMissingBean
        public TransactionManagerCustomizers platformTransactionManagerCustomizers(ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) {
            return new TransactionManagerCustomizers((Collection)customizers.orderedStream().collect(Collectors.toList()));
        }
    
        @Configuration
        @ConditionalOnBean({PlatformTransactionManager.class})
        @ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class})
        public static class EnableTransactionManagementConfiguration {
            public EnableTransactionManagementConfiguration() {
            }
    
            @Configuration
            @EnableTransactionManagement(
                proxyTargetClass = true
            )
            @ConditionalOnProperty(
                prefix = "spring.aop",
                name = {"proxy-target-class"},
                havingValue = "true",
                matchIfMissing = true
            )
          //默认采用cglib代理
            public static class CglibAutoProxyConfiguration {
                public CglibAutoProxyConfiguration() {
                }
            }
    
            @Configuration
            @EnableTransactionManagement(
                proxyTargetClass = false
            )
            @ConditionalOnProperty(
                prefix = "spring.aop",
                name = {"proxy-target-class"},
                havingValue = "false",
                matchIfMissing = false
            )
            public static class JdkDynamicAutoProxyConfiguration {
                public JdkDynamicAutoProxyConfiguration() {
                }
            }
        }
    
        @Configuration
      //当PlatformTransactionManager类型的bean存在并且当存在多个bean时指定为Primary的 PlatformTransactionManager存在时,该配置类才进行解析
        @ConditionalOnSingleCandidate(PlatformTransactionManager.class)
        public static class TransactionTemplateConfiguration {
            private final PlatformTransactionManager transactionManager;
    
            public TransactionTemplateConfiguration(PlatformTransactionManager transactionManager) {
                this.transactionManager = transactionManager;
            }
    
         // 由于TransactionAutoConfiguration是在DataSourceTransactionManagerAutoConfiguration之后才被解析处理的,而在DataSourceTransactionManagerAutoConfiguration中配置了transactionManager,因此, TransactionTemplateConfiguration 会被处理.
            @Bean
            @ConditionalOnMissingBean
            public TransactionTemplate transactionTemplate() {
                return new TransactionTemplate(this.transactionManager);
            }
        }
    }
PlatformTransactionManager以降の章では、分析します

ヒント:使用@EnableTransactionManagement前のアノテーションを使用すると、少なくとも一つの設定されていることを確認してください。PlatformTransactionManagerビーンのを、それ以外の場合はエラーになります。(もちろん、あなたも達成することができますTransactionManagementConfigurer~~~独占的に提供するために、我々は、一般的にそうしません)

オープンコメントドライバ

    @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 2147483647;
    }

簡単かつ@EnableAsync正確に同じ注釈付き。唯一のことを除いて、@Importイントロデューサは、このクラスに導入します。

比較します

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AsyncConfigurationSelector.class)
    public @interface EnableAsync {
        // 支持自定义注解类型 去支持异步~~~
        Class<? extends Annotation> annotation() default Annotation.class;
        boolean proxyTargetClass() default false;
        AdviceMode mode() default AdviceMode.PROXY;
        int order() default Ordered.LOWEST_PRECEDENCE;
    }

TransactionManagementConfigurationSelector

    public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
        public TransactionManagementConfigurationSelector() {
        }
    
        protected String[] selectImports(AdviceMode adviceMode) {
            switch(adviceMode) {
            case PROXY:
                return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
            case ASPECTJ:
                return new String[]{this.determineTransactionAspectClass()};
            default:
                return null;
            }
        }
    
        private String determineTransactionAspectClass() {
            return ClassUtils.isPresent("javax.transaction.Transactional", this.getClass().getClassLoader()) ? "org.springframework.transaction.aspectj.AspectJJtaTransactionManagementConfiguration" : "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";
        }
    }

まだ見ることができ@EnableAsyncインポートAsyncConfigurationSelector同じことを、から継承しAdviceModeImportSelector、すべての後に、同じパターン、類推することにより、パスベルデン〜

AdviceModeImportSelector現在、三つのサブカテゴリーがされてAsyncConfigurationSelector知られています:TransactionManagementConfigurationSelectorCachingConfigurationSelector、。また、これは裏に焦点を当てていることを示しSpringキャッシュシステム@EnableCaching、およびこのモデルは非常に似て~~~

AutoProxyRegistrar

それはImportBeanDefinitionRegistrarあなたがビーンコンテナを登録するために、独自の定義情報を得ることができ、

    // @since 3.1
    public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
        private final Log logger = LogFactory.getLog(this.getClass());
    
        public AutoProxyRegistrar() {
        }
    
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            boolean candidateFound = false;
            // 这里面需要特别注意的是:这里是拿到所有的注解类型~~~而不是只拿@EnableAspectJAutoProxy这个类型的
            // 原因:因为mode、proxyTargetClass等属性会直接影响到代理得方式,而拥有这些属性的注解至少有:
            // @EnableTransactionManagement、@EnableAsync、@EnableCaching等~~~~
            // 甚至还有启用AOP的注解:@EnableAspectJAutoProxy它也能设置`proxyTargetClass`这个属性的值,因此也会产生关联影响~
            Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
            Iterator var5 = annTypes.iterator();
    
            while(var5.hasNext()) {
                String annType = (String)var5.next();
                AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
                if (candidate != null) {
                    Object mode = candidate.get("mode");
                    Object proxyTargetClass = candidate.get("proxyTargetClass");
                  // 如果存在mode且存在proxyTargetClass 属性
                // 并且两个属性的class类型也是对的,才会进来此处(因此其余注解相当于都挡外面了~)
                    if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                        candidateFound = true;
                        if (mode == AdviceMode.PROXY) {
                          
                        // 它主要是注册了一个`internalAutoProxyCreator`,但是若出现多次的话,这里不是覆盖的形式,而是以优先级的形式
                            AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                          //看要不要强制使用CGLIB的方式(由此可以发现  这个属性若出现多次,是会是覆盖的形式)
                            if ((Boolean)proxyTargetClass) {
                                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                                return;
                            }
                        }
                    }
                }
            }
    
            if (!candidateFound && this.logger.isInfoEnabled()) {
                String name = this.getClass().getSimpleName();
                this.logger.info(String.format("%s was imported but no annotations were found having both 'mode' and 'proxyTargetClass' attributes of type AdviceMode and boolean respectively. This means that auto proxy creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been @Import'ed on the same class where these annotations are declared; otherwise remove the import of %s altogether.", name, name, name));
            }
        }
    }

トラッキングAopConfigUtilsソースコードあなたはこのトランザクションが血管に注入されていることがわかりますInfrastructureAdvisorAutoProxyCreatorし、それが採用されているかどうCGLIBか、JDKエージェントを。これは主に読み込まれAdvisorたクラスを、セカンダリプロキシ豆とラインインチ

プロキシトランザクション管理の設定

    @Configuration
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
        public ProxyTransactionManagementConfiguration() {
        }
    
        @Bean(
            name = {"org.springframework.transaction.config.internalTransactionAdvisor"}
        )
        @Role(2)
        public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            advisor.setTransactionAttributeSource(this.transactionAttributeSource());
            advisor.setAdvice(this.transactionInterceptor());
            if (this.enableTx != null) {
              // 顺序由@EnableTransactionManagement注解的Order属性来指定 默认值为:Ordered.LOWEST_PRECEDENCE
                advisor.setOrder((Integer)this.enableTx.getNumber("order"));
            }
    
            return advisor;
        }
    
        @Bean
        @Role(2)
        // TransactionAttributeSource 这种类特别像 `TargetSource`这种类的设计模式
        public TransactionAttributeSource transactionAttributeSource() {
            return new AnnotationTransactionAttributeSource();
        }
    
        @Bean
        @Role(2)
      // 事务拦截器,它是个`MethodInterceptor`,它也是Spring处理事务最为核心的部分
        // 请注意:你可以自己定义一个TransactionInterceptor(同名的),来覆盖此Bean
        public TransactionInterceptor transactionInterceptor() {
            TransactionInterceptor interceptor = new TransactionInterceptor();
            interceptor.setTransactionAttributeSource(this.transactionAttributeSource());
            if (this.txManager != null) {
                interceptor.setTransactionManager(this.txManager);
            }
            return interceptor;
        }
    }
    @Configuration
    public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
        @Nullable
        protected AnnotationAttributes enableTx;
       
      // 此处:注解的默认的事务处理器(可议通过实现接口TransactionManagementConfigurer来自定义配置)
        // 因为事务管理器这个东西,一般来说全局一个就行,但是Spring也提供了定制化的能力~~~
          @Nullable
        protected PlatformTransactionManager txManager;
    
        public AbstractTransactionManagementConfiguration() {
        }
    
        public void setImportMetadata(AnnotationMetadata importMetadata) {
            this.enableTx = AnnotationAttributes.fromMap(importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
          //这个注解@EnableTransactionManagement是必须的~~~~~~~~~~~~~~~~否则报错了
            if (this.enableTx == null) {
                throw new IllegalArgumentException("@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
            }
        }
    
        @Autowired(
            required = false
        )
      // 这里和@Async的处理一样,配置文件可以实现这个接口。然后给注解驱动的给一个默认的事务管理器~~~~
        void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
            if (!CollectionUtils.isEmpty(configurers)) {
              // 同样的,最多也只允许你去配置一个~~~
                if (configurers.size() > 1) {
                    throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
                } else {
                    TransactionManagementConfigurer configurer = (TransactionManagementConfigurer)configurers.iterator().next();
                    this.txManager = configurer.annotationDrivenTransactionManager();
                }
            }
        }
    
        @Bean(
            name = {"org.springframework.transaction.config.internalTransactionalEventListenerFactory"}
        )
        @Role(2)
        public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
            return new TransactionalEventListenerFactory();
        }
    }

BeanFactoryTransactionAttributeSourceAdvisor

ファイル

TransactionAttributeSourcePointcut

これは、事務の一致であるPointcutセクションには、トランザクションを適用するためにプロキシオブジェクトを生成する必要がどのクラスを決定します。

    // 首先它的访问权限事default 显示是给内部使用的
    // 首先它继承自StaticMethodMatcherPointcut   所以`ClassFilter classFilter = ClassFilter.TRUE;` 匹配所有的类
    // 并且isRuntime=false  表示只需要对方法进行静态匹配即可~~~~
    abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
    
        // 方法的匹配  静态匹配即可(因为事务无需要动态匹配这么细粒度~~~)
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            // 实现了如下三个接口的子类,就不需要被代理了  直接放行
            // TransactionalProxy它是SpringProxy的子类。  如果是被TransactionProxyFactoryBean生产出来的Bean,就会自动实现此接口,那么就不会被这里再次代理了
            // PlatformTransactionManager:spring抽象的事务管理器~~~
            // PersistenceExceptionTranslator对RuntimeException转换成DataAccessException的转换接口
            if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
                    PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
                    PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
                return false;
            }
            
            // 重要:拿到事务属性源~~~~~~
            // 如果tas == null表示没有配置事务属性源,那是全部匹配的  也就是说所有的方法都匹配~~~~(这个处理还是比较让我诧异的~~~)
            // 或者 标注了@Transaction这样的注解的方法才会给与匹配~~~
            TransactionAttributeSource tas = getTransactionAttributeSource();
            return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
        }   
        ...
        // 由子类提供给我,告诉事务属性源~~~
        @Nullable
        protected abstract TransactionAttributeSource getTransactionAttributeSource();
    }

@Transactional

このトランザクション注釈をクラスで使用することができ、それはまた、この方法で使用することができます。

  • 各サービスメソッドサービスコンポーネントの同等のサービス・コンポーネント・クラス・レベルをマークするトランザクションアノテーションは、このコメントに適用され
  • アプリケーションは、メソッドレベルで業務ノートよりきめの細かい道総務ノートです

注:トランザクションの注釈法上のプロパティとメソッドにそのクラス、優先利用トランザクション注釈プロパティのメソッドを持っている場合。

また、春は、3つの異なるトランザクションが注意サポートされています。

  • 春のトランザクションのコメントorg.springframework.transaction.annotation.Transactional
  • JTAのトランザクション注釈・javax.transaction.Transactional・
  • EJB 3トランザクション注釈・javax.ejb.TransactionAttribute・

カスタムTransactionManagementConfigurer

    @Configuration
    @EnableTransactionManagement
    public class MyTransactionManagementConfigurer implements TransactionManagementConfigurer {
        @Bean
        public PlatformTransactionManager transactionManager(DataSource dataSource) {
            DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource);
            return dataSourceTransactionManager;
        }
    
        @Override
        public PlatformTransactionManager annotationDrivenTransactionManager() {
            return null;
        }
    }

@EnableAspectJAutoProxyと@EnableTransactionManagement優先?

  • @EnableAspectJAutoProxy私は、血管注射をしたいと思いますAnnotationAwareAspectJAutoProxyCreator
  • @EnableTransactionManagement私は、血管注射をしたいと思いますInfrastructureAdvisorAutoProxyCreator
    public abstract class AopConfigUtils {
        ...
        @Nullable
        private static BeanDefinition registerOrEscalateApcAsRequired(
                Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
            
            // 可以发现这里有一个很巧妙的处理:会对自动代理创建器进行升级~~~~
            // 所以如果你第一次进来的是`InfrastructureAdvisorAutoProxyCreator`,第二次进来的是`AnnotationAwareAspectJAutoProxyCreator`,那就会取第二次进来的这个Class
            // 反之则不行。这里面是维护的一个优先级顺序的,具体参看本类的static代码块,就是顺序  最后一个`AnnotationAwareAspectJAutoProxyCreator`才是最为强大的
            if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
                BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
                if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                    int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                    int requiredPriority = findPriorityForClass(cls);
                    if (currentPriority < requiredPriority) {
                        apcDefinition.setBeanClassName(cls.getName());
                    }
                }
                return null;
            }
    
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
            beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
            registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
            return beanDefinition;
        }
        ...
    }

上記の分析から、我々は知ることができます:あなたはどのように多くのこれらのノートのかどうかに関係なく、自分のための、それは互換性のカバレッジを確保するために、わずかに下向きの優先ブーストの内部機構を有しています。そのため、通常の状況下では、我々は最も先進的な使用しているAnnotationAwareAspectJAutoProxyCreator~~~自動プロキシクリエータを

おすすめ

転載: www.cnblogs.com/qinzj/p/11420840.html