Detailed explanation of SpringBoot's automatic configuration principle (source code analysis)

Introduction

SpringBoot is a popular technology today, and it is also a skill item that we must master. Its emergence benefits from the concept of " convention is greater than configuration" . It does not require cumbersome configuration of xml and bean like the Spring framework. , There is no content that is difficult to integrate, we can use SpringBoot to quickly develop Web, and the automatic configuration function of SpringBoot is also really fragrant, but while using the framework to bring us convenience, we must not forget the underlying implementation. Often a technology allows While our development is faster, it also makes it easier for us to ignore the underlying implementation. Next, let's analyze how the underlying source code of SpringBoot automatic configuration is implemented.

SpringBoot configuration file

Those who have studied SpringBoot all know that SpringBoot has a global configuration file: application.properties/yml. The things we need to configure are basically configured in this file. For example, the most commonly used configuration has the port at startup: server. Port, etc., in the official SpringBoot document about the configuration file gives a lot of configuration options, please see the official SpringBoot document for details .
Insert picture description here
Do you have to memorize all the configuration? It is estimated that I will not be able to memorize it until next year. With so many configurations, it is impossible to memorize it. The most important thing is to understand that we will not use all of these configurations, but we have questions about these configurations. Why Can SpringBoot be configured here automatically to take effect? How do they take effect in the SpringBoot project? Soon we will start to introduce in detail through the source code.

The source code location of SpringBoot's automatic configuration is:

The source location of SpringBoot's automatic configuration is: spring-boot-autoconfigure-XXXRELEASE.jar
Insert picture description here

Source code analysis of SpringBoot automatic configuration principle

@SpringBootApplication

First of all, we all know that a new SpringBoot project will have a startup class, and there is an @SpringBootApplicationannotation on the startup class . It is the core annotation of SpringBoot. It has a lot to do with SpringBoot's automatic configuration principle. We can click into it. Take a look at the bottom layer of this annotation.
Insert picture description here

@EnableAutoConfiguration

Insert picture description here
We clicked into the @SpringBootApplicationannotation and found that it turned out to be a compound annotation (derived annotation), and there is a @EnableAutoConfigurationannotation in it. According to our Chinese translation, it actually means that it can (turn on) automatic configuration. Here we first remember this annotation . This annotation is mentioned in the source code later, and we click into this @EnableAutoConfiguration annotation to view its underlying layer.

@Import(AutoConfigurationImportSelector.class)

We found that this @EnableAutoConfiguration annotation is also a derived annotation, but the key function inside is provided by @Import, which imports AutoConfigurationImportSelector.class. What is this?
Let's check it according to the source code in turn. First, we find the selectImports method in
Insert picture description here
this class. This method calls the getAutoConfigurationEntry (annotationMetadata) method to obtain the automatic configuration instance. Let's continue to check in this method.

  • Discovery getAutoConfigurationEntry(annotationMetadata)method calls getCandidateConfigurations(annotationMetadata, attributes)to get the configuration candidate;
  • And in getCandidateConfigurations(annotationMetadata, attributes); call the SpringFactoriesLoader.loadFactoryNames().loadSpringFactories()method to load the Spring factory;
  • In loadSpringFactories()the source code of the classLoader.getResources(FACTORIES_RESOURCE_LOCATION)method , the method is called to load the resource. FACTORIES_RESOURCE_LOCATIONThe definition in the source code is:public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
  • Finally, the file at this location was loaded, and the jar package with META-INF/spring.factories was scanned.

The above summary is: the selectImports() method of the imported AutoConfigurationImportSelector scans all jar packages with META-INF/spring.factories through SpringFactoriesLoader.loadFactoryNames(). There is such a spring.factories file in spring-boot-autoconfigure-xxxxjar.

We open the spring.factories file and find that there is a group of key=value forms, one of which is the full class name of the EnableAutoConfiguration class, and its value is a list of xxxxAutoConfiguration class names, these class names are commas Separate, as shown in the figure below:
Insert picture description here
Insert picture description here
and the @EnableAutoConfiguration annotation is first related to the SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader()) method in getCandidateConfigurations, where the method getSpringFactoriesLoaderFactoryClass() returns EnableAutoConfiguration.class, as shown below Show: It
Insert picture description here
means to return all resources under the class marked by @EnableAutoConfiguration annotation, and @EnableAutoConfiguration annotation is inherited by @SpringBootApplication annotation, and finally is indirectly marked on the startup class of Springboot, and at the same time in SpringApplication.run(...) The internal execution of the selectImports() method in AutoConfigurationImportSelector finds the class corresponding to the fully qualified name of all JavaConfig auto-configuration classes, and then loads all the auto-configuration classes into the Spring container.

About the effective of automatic configuration

Each XxxxAutoConfiguration automatic configuration class in the spring.factories file is marked with some conditional judgment annotations, which means that these configuration classes will take effect only when certain conditions are met, and these conditions are restricted in SpringBoot Reflected in the form of comments, common conditional comments are as follows:

Conditional comment Description
ConditionalOnJava Does the java version of the system meet the requirements?
ConditionalOnBean When there are specified beans in the container.
ConditionalOnMissingBean When the specified bean does not exist in the container.
ConditionalOnExpression Meet the SpEL expression specification
ConditionalOnClass When there is a specified class in the class path.
ConditionalOnMissingClass When the specified class does not exist in the class path.
ConditionalOnSingleCandidate There is only one specified bean in the container, or this bean is the preferred bean
ConditionalOnProperty Whether the specified property has a specified value, for example, ConditionalOnProperty(prefix="xxx.xxx",value="enable",matchlfMissing=ture), which means that when xxx.xxx is enable, the conditional boolean value is true, if it is not set It is also true in the case. Whether the attribute specified in the system has the specified value
ConditionalOnResource Whether the specified resource exists under the classpath
ConditionalOnWebApplication Currently web environment
ConditionalOnNotWebApplication Currently not a web environment
ConditionalOnOnJndi JNDI has specified items

For example, take the port we configure Tomcat to start as an example, such as: server: 8081how to modify the port to take effect, the automatic configuration class for modifying the port is the ServletWebServerFactoryAutoConfiguration class in the spring.factories file, this port is 8080 if not configured, source In org.apache.catalina.startup.Tomcat.

Insert picture description here
We look at the source code through the ServletWebServerFactoryAutoConfiguration class in the spring.factories file, and we can see that there are many annotations marked above. Among them, there is an @EnableConfigurationProperties annotation (open configuration properties), which is responsible for importing this bean with bound properties to spring In the container, the parameter behind it is a ServerProperties class, we can click in and take a look:
Insert picture description here
the @ConfiguratioonProperties annotation is marked on this class, and its role is to bind properties from the configuration file to the corresponding bean, then all other The properties related to this class can be defined in the global configuration file, that is to say, the class that really "limits" which properties we can configure in the global configuration file is these XxxxProperties classes, which are key to the prefix defined in the configuration file The set of attributes at the beginning of the word is uniquely corresponding.

When we configure server:port:8081 in the yml configuration file, it is equivalent to assigning the port attribute in ServerProperties to 8081.

to sum up

At this point, we can roughly understand: in the properties of the global configuration, server.port, etc., are bound to the corresponding Xxxx.Properties configuration entity class through the @ConfiguratioonProperties annotation and encapsulated into a bean, and then passed @EnableConfigurationProperties The annotations are imported into the Spring container.

And many XxxxAutoConfiguration auto-configuration classes are the JavaConfig form of the Spring container, and their role is to import beans for the Spring container, and the properties required by all imported beans are obtained through the xxxxProperties bean.

When Spring Boot starts, it will find all the automatic configuration classes in the META-INF/spring.factories configuration file through the @EnableAutoConfiguration annotation, and load them, and these automatic configuration classes are named after AutoConfiguration, which is actually It is a Spring container configuration class in the form of JavaConfig, which can obtain the properties configured in the global configuration file through the class named at the end of Properties, such as: server.port, and the XxxProperties class is annotated with @ConfigurationProperties corresponding to the global configuration file When the properties are bound, when we set them in the application.yml/properties file, it is equivalent to calling the properties in the corresponding configuration class for assignment.

Reference materials: https://blog.csdn.net/u014745069/article/details/83820511?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog -BlogCommendFromMachineLearnPai2-3.channel_param

Guess you like

Origin blog.csdn.net/weixin_43246215/article/details/108439119