Automatic configuration (startup process)

Posted Jun 16, 20208 min read

2.2 Automatic configuration(startup process)

Concept:when we add jar package dependencies, we can automatically configure the relevant configuration of some components for us. We can run the written project without configuration or only a small amount of configuration.

Question:In the end, how does Spring Boot auto-configure and what components are auto-configured?

The startup entry of the Spring Boot application is the main() method in the @SpringBootApplication annotation annotation class. @SpringBootApplication can scan Spring components and automatically configure Spring Boot

Below, check @SpringBootApplication internal source code for analysis, the core code is as follows

java

@SpringBootApplication

public class SpringbootDemoApplication {

public static void main(String[]args) {

SpringApplication.run(SpringbootDemoApplication.class, args);

}

}

java

@Target({ElementType.TYPE}) //The scope of annotations, Type means that annotations can be described in classes, interfaces, annotations or enumerations

@Retention(RetentionPolicy.RUNTIME) //Indicates the life cycle of the annotation, Runtime runtime

@Documented //Indicates that the annotation can be recorded in javadoc

@Inherited //Indicates that the annotation can be inherited by subclasses

@SpringBootConfiguration //Mark this class as the configuration class

@EnableAutoConfiguration //Start the automatic configuration function

@ComponentScan(//package scanner

excludeFilters = {@Filter(

type = FilterType.CUSTOM,

classes = {TypeExcludeFilter.class}

), @Filter(

type = FilterType.CUSTOM,

classes = {AutoConfigurationExcludeFilter.class}

)}

)

public @interface SpringBootApplication {

...

}

It can be seen from the above source code that the @SpringBootApplication annotation is a combined annotation. The first four are the metadata information of the annotation. We mainly look at the following three annotations:@SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan three core annotations, about these three The relevant explanations of each core note are as follows:

  1. @SpringBootConfiguration annotation

The @SpringBootConfiguration annotation indicates the Spring Boot configuration class. See @SpringBootConfiguration annotation source code, the core code is as follows.

java

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Configuration //Configure the IOC container

public @interface SpringBootConfiguration {

}

It can be seen from the above source code that there is a core annotation @Configuration inside the @SpringBootConfiguration annotation, which is provided by the Spring framework and indicates that the current class is a configuration class(annotation representation form of the XML configuration file) and can be used by the component scanner scanning. It can be seen that the function of @SpringBootConfiguration annotation is the same as @Configuration annotation, both identify a configuration class that can be scanned by the component scanner, but @SpringBootConfiguration is repackaged and named by Spring Boot.

  1. @EnableAutoConfiguration annotation

    @EnableAutoConfiguration annotation indicates that the automatic configuration function is turned on. This annotation is the most important annotation of the Spring Boot framework and is also an annotation for automatic configuration. Similarly, view the source code information inside the annotation, the core code is as follows

![image-20191226121755878](./images/image-20191226121755878.png)

It can be found that it is a combined annotation. There are many annotations starting with Enable in Spring. Its function is to use @Import to collect and register beans related to a specific scene and load it into the IoC container. @EnableAutoConfiguration is to use @Import to collect all bean definitions that meet the automatic configuration conditions and load them into the IoC container.

Here, explain these two core notes separately:

(1) @AutoConfigurationPackage annotation

See @AutoConfigurationPackage annotation internal source information, the core code is as follows:

```java

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Import({Registrar.class}) //Import components registered in Registrar

public @interface AutoConfigurationPackage {

}

It can be seen from the above source code that the function of @AutoConfigurationPackage annotation is implemented by @Import annotation, which is the bottom annotation of the spring framework. Its function is to import a component class into the container, such as @Import(AutoConfigurationPackages.Registrar. class), it is to import the Registrar component class into the container, you can view the registerBeanDefinitions method in the Registrar class, this method is the specific implementation of the imported component class:

![image-20191226122946037](./images/image-20191226122946037.png)

It can be seen from the above source code that there is a registerBeanDefinitions() method in the Registrar class. Use the Debug mode to start the project. You can see that the selected part is com.lagou. In other words, the main function of the @AutoConfigurationPackage annotation is to scan the components in the package where the main program class is located and all the sub-packages into the spring container.

Therefore, when defining the project package structure, it is required that the defined package structure is very standardized. The project main program startup class should be defined at the outermost root directory location, and then the subpackages and classes should be established within the root directory location for business development, so that it can Ensure that the defined classes can be scanned by the component scanner

(2)**@Import({AutoConfigurationImportSelector.class}):**import **AutoConfigurationImportSelector**this class into the spring container,**AutoConfigurationImportSelector** can help The springboot application loads all eligible @Configuration configurations into the current IoC container(ApplicationContext) created and used by SpringBoot

Continue to study **AutoConfigurationImportSelector** this class, through source code analysis, this class is through the method of selectImports to tell springboot that those components need to be imported:

![image-20200119172227144](./images/image-20200119172227144.png)

**In-depth study of loadMetadata method**

![image-20200119172325325](./images/image-20200119172325325.png)

**In-depth getCandidateConfigurations method**

There is an important method loadFactoryNames in this method, this method is to let SpringFactoryLoader to load the names of some components.

![image-20200119172418984](./images/image-20200119172418984.png)

Continue to open the loadFactory method

```java

public static List loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {

//Get the access key

String factoryClassName = factoryClass.getName();

return(List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());

}

private static Map<String, List> loadSpringFactories(@Nullable ClassLoader classLoader) {

MultiValueMap<String, String> result =(MultiValueMap)cache.get(classLoader);

if(result != null) {

return result;

} else {

try {

//If the class loader is not null, load the spring.factories file in the class path and encapsulate the full path information of the configuration class set in it into an Enumeration class object

Enumeration urls = classLoader != null? ClassLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");

LinkedMultiValueMap result = new LinkedMultiValueMap();

//Cycle the Enumeration class object, generate the Properties object according to the corresponding node information, obtain the value through the passed key, and then cut the value into a small string into an Array, method result collection

while(urls.hasMoreElements()) {

URL url =(URL)urls.nextElement();

UrlResource resource = new UrlResource(url);

Properties properties = PropertiesLoaderUtils.loadProperties(resource);

Iterator var6 = properties.entrySet().iterator();

while(var6.hasNext()) {

Entry entry =(Entry)var6.next();

String factoryClassName =((String)entry.getKey()).trim();

String[]var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());

int var10 = var9.length;

for(int var11 = 0; var11 <var10; ++var11) {

String factoryName = var9[var11];

result.add(factoryClassName, factoryName.trim());

}

}

}

cache.put(classLoader, result);

return result;

```

Will go to read a sprin g.factories file, can not read this error, we continue to see, the final path is like this, and this is a tool class provided by spring

```java

public final class SpringFactoriesLoader {

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

}

```

It actually loads an external file, and this file is in

![image-20191226162644636](./images/image-20191226162644636.png)

![image-20191226162832498](./images/image-20191226162832498.png)

@EnableAutoConfiguration is to search the META-INF/spring.factories configuration file from the classpath, and instantiate the configuration items corresponding to org.springframework.boot.autoconfigure.EnableutoConfiguration through reflection(Java Refletion) into the corresponding JavaConfig marked with @Configuration Form configuration class and load it into the IOC container

Taking the previous project as an example, the Web environment dependency launcher is added to the project, and the corresponding WebMvcAutoConfiguration automatic configuration class will take effect. Open the automatic configuration class and you will find that in the configuration class, you can configure Spring by fully annotating the configuration class. The environment required for MVC operation has been configured by default, including default prefix, default suffix, view parser, MVC checker, etc. The essence of these automatic configuration classes is the corresponding XML configuration file in the traditional Spring MVC framework, but it is pre-configured in the form of automatic configuration classes in Spring Boot. Therefore, after adding the relevant dependency starter to the Spring Boot project, you can basically run the program without any configuration. Of course, we can also change the default configuration in these automatic configuration classes.

**to sum up**

Therefore, the steps to implement automatic configuration at the bottom of springboot are:

1. The springboot application starts;

2. @SpringBootApplication works;

3. @EnableAutoConfiguration;

4. @AutoConfigurationPackage:This combination annotation is mainly @Import(AutoConfigurationPackages.Registrar.class), which imports the Registrar class into the container, and the Registrar class is to scan the main configuration class at the same level of the directory and sub-packages, and the corresponding The components are imported into the container created and managed by springboot;

5. @Import(AutoConfigurationImportSelector.class):It imports the AutoConfigurationImportSelector class into the container. The AutoConfigurationImportSelector class is used during the process of execution through the selectImports method. It will use the internal tool class SpringFactoriesLoader to find META- in all jar packages on the classpath INF/spring.factories to load, realize the configuration class information to the SpringFactory loader for a series of container creation process

**3. @ComponentScan annotation**

@ComponentScan Annotation The root path of the specific scanned package is determined by the location of the package where the main program startup class of the Spring Boot project is located. During the scanning process, it is parsed by the @AutoConfigurationPackage annotation introduced earlier to obtain the package of the main program startup class of the Spring Boot project. Specific location

to sum up:

The function of @SpringBootApplication's annotation is almost the analysis, in simple terms it is a combination of 3 annotations:

java

|- @SpringBootConfiguration

|- @Configuration //Add components to the IOC container through javaConfig

|- @EnableAutoConfiguration

|- @AutoConfigurationPackage //Automatic configuration package, added to IOC with @ComponentScan

|- @Import(AutoConfigurationImportSelector.class) //Add the bean defined in META-INF/spring.factories to the IOC container

|- @ComponentScan //Package scanning

I just learned the "Java Engineer High Salary Training Camp" of Lagou Education, and I answered when I saw what I just learned. I hope Lagou can push me to the company I want to go to. Goal:byte! !