Tutorial básico do springboot2.x: princípio @ Enable *

O tutorial básico anterior do springboot 2.x: @Async abre tarefas assíncronas. Usamos a anotação @EnableAsync para habilitar a execução assíncrona.
Existem muitas anotações @ Enable * na estrutura SpringBoot, como: @EnableAspectJAutoProxy, @EnableCaching, @EnableAutoConfiguration, @ EnableSwagger2 Este capítulo explica o princípio por trás disso.

Várias anotações @ Enable * típicas

As três anotações @ EnableSwagger2, @EnableAsync e @EnableAspectJAutoProxy estão postadas abaixo. Não é difícil ver que todas essas três anotações usam a anotação @Import.
A anotação @Import suporta a importação de classes Java comuns e sua declaração como bean.
A anotação @Enable real é injetar Bean no contêiner springboot ioc por meio da capacidade da anotação @Import para fazer certas configurações entrarem em vigor.

@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 annotation using

Permitir classes anotadas com @Configuration

O @Import anotado por @EnableScheduling importa a classe SchedulingConfiguration.Vamos ver a implementação desta classe.
Podemos ver que esta classe usa anotações @Configuration e @Bean.
A anotação @Import permite que as classes anotadas com @Configuration sejam injetadas no contêiner.

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

Permite o uso de classes que implementam a interface ImportSelectorj

@EnableAsync anotado @Import importa a classe AsyncConfigurationSelector, vamos dar uma olhada na implementação dessa classe.
A classe AsyncConfigurationSelector implementa a interface ImportSelector e substitui o método selectImports.
A anotação @Import aqui injetará a classe de caminho completa retornada por selectImports no contêiner.

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

Permitido é uma classe que implementa a interface ImportBeanDefinitionRegistrar

@EnableAspectJAutoProxy anotado @Import importa a classe AspectJAutoProxyRegistrar, vamos dar uma olhada na implementação dessa classe.
AspectJAutoProxyRegistrar implementa a interface ImportBeanDefinitionRegistrar. A função de ImportBeanDefinitionRegistrar é adicionar Beans automaticamente às classes de configuração existentes em tempo de execução e analisar e gerar beans quando o contêiner Spring é iniciado, reescrevendo o método registerBeanDefinitions.

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 annotation Análise de código-fonte do fluxo de processamento do SpringBoot

  1. O método de atualização de AbstractApplicationContext é chamado quando o contêiner Spring IOC é inicializado
  2. Vários BeanFactoryPostProcessor serão chamados na atualização. O método processConfigBeanDefinitions de ConfigurationClassPostProcessor lida com anotações como @Configuration e @Import.
  3. ConfigurationClassPostProcessor é realmente processado internamente por ConfigurationClassParser.
  4. Vamos nos concentrar no tratamento @Import da classe ConfigurationClassParser.

Análise do código-fonte da classe ConfigurationClassParser

O código de processamento principal está no método processImports de ConfigurationClassParser, que implementa o processamento das três maneiras de usar @Import neste artigo.

  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);
                        }
	//....省略部分代码
    }

Mil milhas começam com um único passo. Este é o décimo primeiro artigo da série de tutoriais SpringBoot. Todos os códigos-fonte do projeto podem ser baixados em meu GitHub .

Acho que você gosta

Origin blog.csdn.net/github_35592621/article/details/108248929
Recomendado
Clasificación