SpringBoot auto configuration principle

Posted by Alffallen on Wed, 22 Dec 2021 10:43:24 +0100

SpringBoot auto configuration principle

What is auto configuration?

When learning about SSM development projects, we need to introduce the dependencies of spring, spring MVC and mybatis, and use configuration files or java config to configure components such as configuration view parser. However, springboot provides us with a convenient development method: automatic configuration. We only need to introduce a specific starter, and other required components will be automatically added to the container for us. This is automatic configuration.

How does SpringBoot implement automatic configuration?

This article is based on springboot 2 1.4 writing.

Looking at the main startup class, we find that there is an @ SpringBootApplication annotation on the class, which is the key to the automatic configuration of SpringBoot.

@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
}

Further on, we enter the source code of @ SpringBootApplication annotation and find the following annotation above the annotation:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
      @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
      @Filter(type = FilterType.CUSTOM,
            classes = AutoConfigurationExcludeFilter.class) })

Of which:

  • @SpringBootConfiguration is a Configuration annotation and a combination annotation of the SpringBoot project. It is recommended to use @ SpringBootConfiguration instead of @ Configuration in the SpringBoot project;
  • @The function of ComponentScan is to assemble the classes that meet the scanning rules into the spring container according to the defined scanning path;
  • @EnableAutoConfiguration tells SpringBoot to enable the auto configuration function. The focus of auto configuration is in this annotation.

We recognize the key point of automatic configuration - @ EnableAutoConfiguration, and then we will study this annotation.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

Similarly, we start the analysis one by one.

@AutoConfigurationPackage

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {

}

We checked the @ AutoConfigurationPackage annotation and found that it imported the Registrar class under AutoConfigurationPackages

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

   @Override
   public void registerBeanDefinitions(AnnotationMetadata metadata,
         BeanDefinitionRegistry registry) {
      register(registry, new PackageImport(metadata).getPackageName());
   }

   @Override
   public Set<Object> determineImports(AnnotationMetadata metadata) {
      return Collections.singleton(new PackageImport(metadata));
   }

}

We found that there is a registerBeanDefinitions method in this Registrar class. The main function of this method is to scan the components under the package where the main program class is located and all its sub packages into the Spring container.

@Import(AutoConfigurationImportSelector.class)

**This note is the focus of the focus** This annotation imports the auto configuration class AutoConfigurationImportSelector to the current configuration class.

There is a selectImports method in this class. The function of this method is to inject bean s that need to be injected into the container into the container according to the configuration file (spring.factories). (this method will not be called when SpringBoot starts!!!)

@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
   if (!isEnabled(annotationMetadata)) {
      return NO_IMPORTS;
   }
   AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
         .loadMetadata(this.beanClassLoader);
   AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
         autoConfigurationMetadata, annotationMetadata);
   return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}

There are two main methods used in this method:

  • One is autoconfigurationmetadataloader Loadmetadata, this method will load meta-inf / spring-autoconfigure-metadata under the classpath by default Configuration in properties;
  • The other is getAutoConfigurationEntry.

The getAutoConfigurationEntry method is called when SpringBoot starts, not the selectImports method.

The main function of this method is to load meta-inf / spring Factories, if the @ EnableAutoConfiguration annotation passes in the exclude parameter, the class corresponding to the exclude will be transferred from meta-inf / spring Remove it from the factories and remove it from meta-inf / spring-autoconfigure-metadata The configuration classes with the conditions written in properties are filtered out and all the filtered configuration classes are returned.

protected AutoConfigurationEntry getAutoConfigurationEntry(
      AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
   // Check the automatic assembly switch
   if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
   }
   // Get the parameter in EnableAutoConfiguration, exclude()/excludeName()
   AnnotationAttributes attributes = getAttributes(annotationMetadata);
   // Get all configuration classes that need to be automatically assembled and read meta-inf / spring factories 
   List<String> configurations = getCandidateConfigurations(annotationMetadata,
         attributes);
   // De duplication, List to Set, then List
   configurations = removeDuplicates(configurations);
   // Get exclusions from the exclude/excludeName property of EnableAutoConfiguration
   Set<String> exclusions = getExclusions(annotationMetadata, attributes);
   // Check whether the class to be excluded is in configurations and no error is reported
   checkExcludedClasses(configurations, exclusions);
   // Remove exclusions from configurations
   configurations.removeAll(exclusions);
   // Filter the configurations and eliminate the spring autoconfigure metadata The configuration class of the conditions written in properties   
   configurations = filter(configurations, autoConfigurationMetadata);
   // Listener import event callback
   fireAutoConfigurationImportEvents(configurations, exclusions);
   // Returns the (configurations, exclusions) group 
   return new AutoConfigurationEntry(configurations, exclusions);
}

Are you a little dizzy? In fact, it is to eliminate the non-standard and impermissible, and keep the others and return them.

spring-factories

Don't know where to find spring factories? I haven't seen it. What exactly is it?

If Maven is used as a package management tool, you can find the corresponding version of spring boot autoconfigure package under External Libraries, which contains our spring Factories and spring-autoconfigure-metadata properties.

spring. The factories file stores all the candidate classes to be automatically assembled that spring boot supports by default.

spring-autoconfigure-metadata.properties is the configuration file related to automatic assembly metadata filtering.

Summary

  1. @Import(AutoConfigurationPackages.Registrar.class). The implementation is to scan all packages and sub packages marked by the main configuration class (@ SpringBootApplication) into the Spring container.
  2. @Import(AutoConfigurationImportSelector.class) implements that SpringBoot starts from meta-inf / spring Get the values specified by @ EnableAutoConfiguration from factories and import them into the container as automatic configuration classes. The automatic configuration class will take effect and help us with automatic configuration. (the getAutoConfigurationEntry method is called when SpringBoot starts, not the selectImports method.)

Topics: Spring Spring Boot