springboot2.x基本チュートリアル:@ Enable *原則

以前のspringboot 2.x基本チュートリアル:@Asyncは非同期タスクを開くため、@ EnableAsyncアノテーションを使用して非同期実行を有効にしました。
SpringBootフレームワークには、@ EnableAspectJAutoProxy、@ EnableCaching、@ EnableAutoConfiguration、@ EnableSwagger2など、多くの@ Enable *アノテーションがあります。この章では、その背後にある原理について説明します。

いくつかの典型的な@ Enable *アノテーション

@ EnableSwagger2、@ EnableAsync、@ EnableAspectJAutoProxyの3つのアノテーションを以下に掲載しますが、これらの3つのアノテーションがすべて@Importアノテーションを使用していることを確認するのは難しくありません。
@Importアノテーションは、一般的なJavaクラスのインポートとBeanとしての宣言をサポートしています。
実際の@Enableアノテーションは、@ Importアノテーションの機能を介してBeanをspringboot iocコンテナに注入し、特定の構成を有効にします。

@EnableScheduling

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({SchedulingConfiguration.class})
@Documented
public @interface EnableScheduling {
}

@EnableAsync

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

@EnableAspectJAutoProxy

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AspectJAutoProxyRegistrar.class})
public @interface EnableAspectJAutoProxy {
    boolean proxyTargetClass() default false;

    boolean exposeProxy() default false;
}

@Importアノテーションの使用法

@Configuration注釈付きクラスを許可する

@EnableSchedulingによって注釈が付けられた@ImportはSchedulingConfigurationクラスをインポートしますこのクラスの実装を見てみましょう。
このクラスは@Configurationおよび@Beanアノテーションを使用していることがわかります。
@Importアノテーションを使用すると、@ Configurationアノテーションが付けられたクラスをコンテナに注入できます。

@Configuration
@Role(2)
public class SchedulingConfiguration {
    public SchedulingConfiguration() {
    }
    @Bean(
        name = {"org.springframework.context.annotation.internalScheduledAnnotationProcessor"}
    )
    @Role(2)
    public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
        return new ScheduledAnnotationBeanPostProcessor();
    }
}

ImportSelectorjインターフェースを実装するクラスの使用を許可します

@EnableAsyncアノテーション付き@ImportはAsyncConfigurationSelectorクラスをインポートします。このクラスの実装を見てみましょう。
AsyncConfigurationSelectorクラスはImportSelectorインターフェイスを実装し、selectImportsメソッドをオーバーライドします。
ここの@Importアノテーションは、selectImportsによって返されたフルパスクラスをコンテナに注入します。

public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
    private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME = "org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";

    public AsyncConfigurationSelector() {
    }

    @Nullable
    public String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        case PROXY:
            return new String[]{ProxyAsyncConfiguration.class.getName()};
        case ASPECTJ:
            return new String[]{"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration"};
        default:
            return null;
        }
    }
}

Allowedは、ImportBeanDefinitionRegistrarインターフェースを実装するクラスです。

@EnableAspectJAutoProxyアノテーション付き@Importは、AspectJAutoProxyRegistrarクラスをインポートします。このクラスの実装を見てみましょう。
AspectJAutoProxyRegistrarはImportBeanDefinitionRegistrarインターフェースを実装します。ImportBeanDefinitionRegistrarの役割は、実行時に既存の構成クラスにBeanを自動的に追加し、メソッドregisterBeanDefinitionsを書き換えて、Springコンテナの起動時にBeanを解析および生成することです。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    AspectJAutoProxyRegistrar() {
    }

    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
        AnnotationAttributes enableAspectJAutoProxy = AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
        if (enableAspectJAutoProxy != null) {
            if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

            if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
                AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
            }
        }
    }
}

@ImportアノテーションSpringBoot処理フローのソースコード分析

  1. Spring IOCコンテナが初期化されると、AbstractApplicationContextの更新メソッドが呼び出されます
  2. さまざまなBeanFactoryPostProcessorが更新時に呼び出されます。ConfigurationClassPostProcessorのprocessConfigBeanDefinitionsメソッドは、@ Configurationや@Importなどの注釈を処理します。
  3. ConfigurationClassPostProcessorは、実際にはConfigurationClassParserによって内部的に処理されます。
  4. ConfigurationClassParserクラスの@Import処理に注目しましょう。

ConfigurationClassParserクラスのソースコード分析

コア処理コードはConfigurationClassParserのprocessImportsメソッドにあり、この記事で@Importを使用する3つの方法の処理を実装しています。

  private void processImports(ConfigurationClass configClass, ConfigurationClassParser.SourceClass currentSourceClass, Collection<ConfigurationClassParser.SourceClass> importCandidates, Predicate<String> exclusionFilter, boolean checkForCircularImports) {
	//....省略部分代码
                        ConfigurationClassParser.SourceClass candidate = (ConfigurationClassParser.SourceClass)var6.next();
                        Class candidateClass;
                        if (candidate.isAssignable(ImportSelector.class)) {
							//对于处理ImportSelector注解处理
                            candidateClass = candidate.loadClass();
                            ImportSelector selector = (ImportSelector)ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class, this.environment, this.resourceLoader, this.registry);
                            Predicate<String> selectorFilter = selector.getExclusionFilter();
                            if (selectorFilter != null) {
                                exclusionFilter = exclusionFilter.or(selectorFilter);
                            }
                            if (selector instanceof DeferredImportSelector) {
                                this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector)selector);
                            } else {
                                String[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());
                                Collection<ConfigurationClassParser.SourceClass> importSourceClasses = this.asSourceClasses(importClassNames, exclusionFilter);
                                this.processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);
                            }
                        } else if (candidate.isAssignable(ImportBeanDefinitionRegistrar.class)) {
							//对于ImportBeanDefinitionRegistrar接口处理
                            candidateClass = candidate.loadClass();
                            ImportBeanDefinitionRegistrar registrar = (ImportBeanDefinitionRegistrar)ParserStrategyUtils.instantiateClass(candidateClass, ImportBeanDefinitionRegistrar.class, this.environment, this.resourceLoader, this.registry);
                            configClass.addImportBeanDefinitionRegistrar(registrar, currentSourceClass.getMetadata());
                        } else {
                            this.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());
							//对于@Configuration注解处理
                            this.processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
                        }
	//....省略部分代码
    }

千マイルは単一のステップから始まります。これは、SpringBootチュートリアルシリーズの11番目の記事で、すべてのプロジェクトのソースコードはGitHubからダウンロードできます

おすすめ

転載: blog.csdn.net/github_35592621/article/details/108248929