SpringBoot-principle of automatic assembly

 

Reply:

  • When writing a SpringBoot project, @SpringBootApplication is the most common annotation, we can look at the source code inside:

Insert picture description here

  • This includes:
  1. @SpringBootConfiguration
    • We clicked in and learned from the source code that he is a @Configuration, so it is the encapsulation of spring native annotations
  2. @EnableAutoConfiguration
  3. @ComponentScan
    • The default scan is the class of the same level or all classes under the same level package, which is one of spring's native annotations

@EnableAutoConfiguration (the highlight-the core of automatic assembly )

  • Once this annotation is added, the automatic assembly function will be turned on. To put it simply, Spring will try to find all configured Beans under its own classpath and then assemble it.
  • When assembling the Bean, it will be initialized according to several (Conditional) custom rules. Let's take a look at its source code:

Insert picture description here
Insert picture description here
Insert picture description here

  • This interface is mainly for importing @Configuration configuration items, and DeferredImportSelector is a deferred import, which will be executed after all @Configuration has been processed.
  • Looking back, let's take a look at the core method selectImport of AutoConfigurationImportSelector.
//自动装配的方法
@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);
}
  • The method will first determine whether to perform automatic assembly, and then read metadata and metadata related properties from META-INF/spring-autoconfigure-metadata.properties, and then call the getCandidateConfigurations method:
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;
}
  • Here again we meet our old acquaintance-SpringFactoryiesLoader, it will read the configuration of EnableAutoConfiguration under META-INF/spring.factories, and then exclude and filter, and then get the class that needs to be assembled. Finally, let all AutoConfigurationImportListener configured under META-INF/spring.factories execute the AutoConfigurationImportEvent event, the code is as follows:
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);
    }

to sum up:

Auto-assembly still uses SpringFactoriesLoader to load all the EnableAutoConfgruation configured in the META-INF/spring.factoires file. It will go through operations such as exclude and filter to determine the class to be assembled.

Guess you like

Origin blog.csdn.net/qq_33762302/article/details/115180734