Principle of Spring Boot Automatic Configuration

Posted by trauch on Thu, 15 Aug 2019 15:59:43 +0200

springboot's automatic configuration is one of her core functions, which has played a major role in simplifying our configuration files. In this paper, we will simply explore the principle of spring boot automatic configuration, welcome your comments and discussion.

1. SpringBoot loads the main configuration class when it starts, and the automatic configuration function @EnableAutoConfiguration is turned on.

Here, you might as well click on this annotation to see its internal implementation:
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {

2. @Enable AutoConfiguration function:

Import some components into the container using Enable AutoConfiguration Import Selector
Click on the import selector to see the contents of the selectImports() method.

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

There are two main approaches involved.

1.AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader):

public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
        return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
    }

This method is to scan META INF/spring.factories under all jar package classpath
Wrap the contents of the scanned files into properties objects

2.getAutoConfigurationEntry,

Let's look at the implementation of this method:

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata, AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return EMPTY_ENTRY;
        } else {
            AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
            List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
            configurations = this.removeDuplicates(configurations);
            Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
            this.checkExcludedClasses(configurations, exclusions);
            configurations.removeAll(exclusions);
            configurations = this.filter(configurations, autoConfigurationMetadata);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

This method is to get the corresponding values of the EnableAutoConfiguration.class class (class name) from properties, and then add them to the container (to get candidate configurations)
These two methods add the values of all EnableAutoConfiguration configured in META-INF/spring.factories under the class path to the container.
Each of these xxxAutoConfiguration classes is a component of the container that is added to the container; they are used for automatic configuration;

3. Each automatic configuration class has the function of automatic configuration. Taking Http Encoding AutoConfiguration (Http Encoding AutoConfiguration) as an example, the principle of automatic configuration is explained.

@Configuration //Represents that this is a configuration class. Like previous configuration files, components can also be added to containers.
@EnableConfigurationProperties(HttpEncodingProperties.class) //Starting the specified class
ConfigurationProperties Functions; the corresponding values in the configuration file and HttpEncodingProperties Bind; and bind.
HttpEncodingProperties Join in ioc In containers
@ConditionalOnWebApplication //Spring underlying @Conditional annotation (Spring annotation version), depending on the conditions, if
//If the specified conditions are met, the configuration in the entire configuration class will take effect; determine whether the current application is a web application, and if so, the current configuration class will take effect.
@ConditionalOnClass(CharacterEncodingFilter.class) //Determine whether the current project has this class
CharacterEncodingFilter;SpringMVC Filters for scrambling resolution;
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing =
true) //Determine whether a configuration spring.http.encoding.enabled exists in the configuration file; if it does not exist, the judgement is valid
//Even if we do not configure pring.http.encoding.enabled=true in our configuration file, it will take effect by default.
public class HttpEncodingAutoConfiguration {
//He has mapped to SpringBook's configuration file
private final HttpEncodingProperties properties;
//With only one parametric constructor, the value of the parameter is taken from the container.
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
} 
@Bean //Add a component to the container, some values of which need to be obtained from properties
@ConditionalOnMissingBean(CharacterEncodingFilter.class) //Judging that the container does not have this component?
public CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
return filter;
}

According to the current different conditions, determine whether the configuration class is valid or not.
But this configuration class takes effect; the configuration class adds components to the container; the properties of these components are obtained from the corresponding properties class.
Of course, every attribute in these classes is bound to the configuration file.

4. All attributes configurable in the configuration file are encapsulated in the xxxxProperties class; what the configuration file can configure can refer to a certain work.

The corresponding attribute class

@ConfigurationProperties(prefix = "spring.http.encoding") //Get the specified value and the bean's genus from the configuration file
//Sex binding
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF‐8");

Essence:
1) SpringBoot boot loads a large number of automatic configuration classes
2) Let's see if we need SpringBoot's default auto-configuration classes.
3) Let's look at what components are configured in this automatic configuration class; (As long as we have components to use, we don't need to configure any more.)
4) When adding components to automatic configuration classes in containers, some properties are obtained from properties classes. We can specify this in the configuration file
The value of some attributes;
XxxxAutoConfiguration artion: Autoconfigure classes;
Adding components to containers
xxxxProperties: Encapsulate related properties in configuration files;

Topics: Spring encoding SpringBoot Attribute