SpringBoot——自动装配原理

回答:

  • 在编写SpringBoot项目时,@SpringBootApplication是最常见的注解了,我们可以看一下里面的源代码:

在这里插入图片描述

  • 这里面包含了:
  1. @SpringBootConfiguration
    • 我们点进去通过源码得知他是一个@Configuration,所以也就是对spring原生注解的封装
  2. @EnableAutoConfiguration
  3. @ComponentScan
    • 默认扫描的是与该类同级的类或者同级包下的所有类,是spring的原生注解之一

@EnableAutoConfiguration重头戏——自动装配核心

  • 一旦加上此注解,那么将会开启自动装配功能,简单点讲,Spring会试图在自己的classpath(类路径)下找到所有配置的Bean然后进行装配。
  • 装配Bean时,会根据若干个(Conditional)定制规则来进行初始化。我们看一下它的源码:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 该接口主要是为了导入@Configuration的配置项,而DeferredImportSelector是延期导入,当所有的@Configuration都处理过后才会执行。
  • 回过头来我们看一下AutoConfigurationImportSelector的自动配备核心方法 selectImport
//自动装配的方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) { //判断是否自动装配
      return NO_IMPORTS;
   }
   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   //获取所有元数据信息
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   //获取所有加载bean的条件配置
   List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
   //过滤并删除掉重复的bean
   configurations = removeDuplicates(configurations);
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   checkExcludedClasses(configurations, exclusions);
   configurations.removeAll(exclusions);
   configurations = getConfigurationClassFilter().filter(configurations);
   fireAutoConfigurationImportEvents(configurations, exclusions);
   return new AutoConfigurationEntry(configurations, exclusions);
}
  • 该方法刚开始会先判断是否进行自动装配,而后会从META-INF/spring-autoconfigure-metadata.properties读取元数据与元数据的相关属性,紧接着会调用getCandidateConfigurations方法:
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
   List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
         getBeanClassLoader());
   Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
         + "are using a custom packaging, make sure that file is correct.");
   return configurations;
}
  • 在这里又遇到我们的老熟人了–SpringFactoryiesLoader, 它会读取META-INF/spring.factories下的EnableAutoConfiguration的配置,紧接着在进行排除与过滤,进而得到需要装配的类。最后让所有配置在META-INF/spring.factories下的AutoConfigurationImportListener执行AutoConfigurationImportEvent事件,代码如下:
private void fireAutoConfigurationImportEvents(List<String> configurations,
            Set<String> exclusions) {
        List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
        if (!listeners.isEmpty()) {
            AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this,
                    configurations, exclusions);
            for (AutoConfigurationImportListener listener : listeners) {
                invokeAwareMethods(listener);
                listener.onAutoConfigurationImportEvent(event);
            }
        }
    }

    protected List<AutoConfigurationImportListener> getAutoConfigurationImportListeners() {
        return SpringFactoriesLoader.loadFactories(AutoConfigurationImportListener.class,
                this.beanClassLoader);
    }

总结:

自动装配还是利用了SpringFactoriesLoader来加载META-INF/spring.factoires文件里所有配置的EnableAutoConfgruation,它会经过exclude和filter等操作,最终确定要装配的类

猜你喜欢

转载自blog.csdn.net/qq_33762302/article/details/115180734