spring boot自动装配之@EnableAutoConfiguration详解

1、@EnableAutoConfiguration作用

@EnableAutoConfiguration用于类或接口上,在spring boot中注解位于@SpringBootApplication注解上

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
……
}

 当spring boot扫描到@EnableAutoConfiguration注解时则会将spring-boot-autoconfigure.jar/META-INF/spring.factories文件中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value里的所有xxxConfiguration类加载到IOC容器中。而xxxAutoConfiguration类一般都会有@ConditionalOnxxx注解,通过这些条件注解来判断是否真正的创建xxxConfiguration对象。spring boot的各种spring-boot-starter-xxx.jar也正是居于此注解来达到自动装配的目的。

@ConditionalOnxxx常见注解如下:

@ConditionalOnClass classpath中存在该类时起效
@ConditionalOnMissingClass classpath中不存在该类时起效
@ConditionalOnBean DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression SpEL表达式结果为true时
@ConditionalOnProperty 参数设置或者值一致时起效
@ConditionalOnResource 指定的文件存在时起效
@ConditionalOnJndi 指定的Java版本存在时起效
@ConditionalOnWebApplication Web应用环境下起效
@ConditionalOnNotWebApplication 非Web应用环境下起效

2、spring boot处理@EnableAutoConfiguration源码分析

通过《spring boot自动装配原理之@ComponentScan详解》一文我们知道spring boot自动装配的过程都是在ConfigurationClassPostProcessor这个BeanFactoryPostProcessor类中完成的。

核心流程如下:

public class ConfigurationClassPostProcessor {
…………
ConfigurationClassParser parser = new ConfigurationClassParser(
      this.metadataReaderFactory, this.problemReporter, this.environment,
      this.resourceLoader, this.componentScanBeanNameGenerator, registry);

Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
do {
  //1、该方法执行完后会将这pring-boot-autoconfigure.jar/META-INF/spring.factories文件
//中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value值全部封装
//成ConfigurationClass对象存在parser对象的configurationClasses属性中。
   parser.parse(candidates);
   parser.validate();
   //2、取出ConfigurationClass对象
   configClasses.removeAll(alreadyParsed);
   Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());

   // Read the model and create bean definitions based on its content
   if (this.reader == null) {
      this.reader = new ConfigurationClassBeanDefinitionReader(
            registry, this.sourceExtractor, this.resourceLoader, this.environment,
            this.importBeanNameGenerator, parser.getImportRegistry());
   }
//3、将ConfigurationClass转换成ConfigurationClassBeanDefinition并注册到beanFactory中,
//以供后面创建具体的对象,该方法也很复杂,本文不深入研究
   this.reader.loadBeanDefinitions(configClasses);
   alreadyParsed.addAll(configClasses);
…………
}

下面是重点过程方法的拆分,断点走向:

ConfigurationClassPostProcessor.parse(……) --> this.deferredImportSelectorHandler.process(……) --> AutoConfigurationImportSelector.getCandidateConfigurations(……) --> SpringFactoriesLoader.loadFactoryNames(……) --> ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(……)

断点进入parse方法:

public void parse(Set<BeanDefinitionHolder> configCandidates) {
   ……
   this.deferredImportSelectorHandler.process();
}

 进入 this.deferredImportSelectorHandler.process();断点一直跟踪到AutoConfigurationImportSelector的下面方法

protected AutoConfigurationEntry getAutoConfigurationEntry(
      AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
//这个列表对应pring-boot-autoconfigure.jar/META-INF/spring.factories文件中
//org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的value值
   List<String> configurations = getCandidateConfigurations(annotationMetadata,
         attributes);
   configurations = removeDuplicates(configurations);
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   configurations = filter(configurations, autoConfigurationMetadata);
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}
……
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
      AnnotationAttributes attributes) {
   //加载属性文件中xxxAutoConfiguration配置
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
         getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
   ……
   return configurations;
}

this.reader.loadBeanDefinitions(configClasses);方法执行完成后的截图如下:

当所有xxxConfiguration类转换成BeanDefinition对象并注册到DefaultListableBeanFactory后,后面就可以创建具体的bean对象了。

猜你喜欢

转载自blog.csdn.net/mapleleafforest/article/details/87273213