Automatic configuration principle of spring boot 2

Posted by davissj on Fri, 24 Dec 2021 19:09:24 +0100

Today, I learned the automatic configuration principle of springboot 2 and thought it was very clever, so I recorded my learning experience.

1. Preliminary knowledge

Before introducing the automatic assembly principle of springboot 2, there are several annotations that we need to understand. In my opinion, these annotations are the basis of the automatic assembly principle.

1.1 @Conditional assembly

The annotation here is not only @ Conditional, but has the same function as @ Conditional, such as the following annotation:

This annotation is used to inject components only when the conditions specified by Conditional are met.

       1.2 @Import

Imports components of the specified type into the container

2 automatic configuration principle

2.1 automatic loading configuration class

After entering the startup class of SpringBoot2, you can see three important annotations, as follows:

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
)

Among them, @ SpringBootConfiguration indicates that this is a configuration class, @ ComPonentScan is to scan those packages. The most important of the three is the @ EnableAutoConfiguration annotation. The source code is as follows:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
====The following are more important======
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {

        @AutoConfigurationPackager

The source code of important parts is as follows:

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};
}

Where @ Import({Registrar.class}) is used to import components of Registrar type into the container.

Enter Register to see the following methods

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

Where new autoconfigurationpackages PackageImports(metadata)). Getpackagenames () is used to get the package name of the main class, and then encapsulate it into an array. After that, the register scans all qualified components under the package, and then registers them into the container.

Therefore, the @ AutoConfigurationPackager annotation is used to import the components under the specified package into the container. By default, it is under the package where the startup class is located. This also shows that when the relevant configuration is not modified, we need to write other components in the directory of the startup class.

       @Import({AutoConfigurationImportSelector.class})

This annotation imports components of AutoConfigurationImportSelector type. Enter the AutoConfigurationImportSelector code to see the following methods:

    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(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.getConfigurationClassFilter().filter(configurations);
            this.fireAutoConfigurationImportEvents(configurations, exclusions);
            return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
        }
    }

In list < string > configurations = this Getcandidateconfigurations (annotation metadata, attributes) break points can be obtained:

It can be seen that this method is used to obtain the components that need to be imported into the container. If you enter this method again, you can get the most critical method, called loadspring factories. There are too many source codes, so you won't paste them all. We can see this statement in the source code of loadspring factories. Enumeration URLs = classloader The purpose of getresources ("META-INF/spring.factories") is to load meta-inf / spring Factories file, which scans all meta-inf / spring files in our current system by default Factories file.

And spring-boot-autoconfigure-2.6 1. Meta-inf / spring. Jar package also contains meta-inf Factories. This file contains all the configuration classes that spring boot will load into the container as soon as it starts,

2.2 turn on automatic configuration items on demand

It says meta-inf / spring The automatic configuration of all scenarios in the factories file is loaded by default at startup, but not so much at the final configuration, because it will be configured on demand, and some components will not be configured.

In spring boot 2, the solution of on-demand configuration is mainly to use @ Conditional and its annotations with the same function

Here is an example:
For example, the following annotations are used in Aop in spring boot 2

    @ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})

That is, the Advice class will put Aop into the container.

3. Automatic assembly process of springboot 2

That is, meta-inf / spring is loaded at startup All configurations in factories, but they cannot all take effect according to @ Conditional and its annotation with the same function, so as to ensure on-demand assembly.

In this way, if you are not frightened by thousands of source codes, the automatic assembly principle of springboot 2 is very simple. Come on. There is no end to learning.

Topics: Java Spring Boot Back-end source code