Recently, a reader was asked this question in an interview: “Springboot is used in your project. How does springboot auto-configuration work?” This should be one of the most common interview questions in Springboot. Let’s take this problem together with the anatomy of springBoot automatic configuration principle.
SpringMvc vs. SpringBoot
First of all, let’s review the original Hello Word Web project (XML configuration) that built a SpringMVC, whether we need to import various dependencies in the POM, and then each dependency may have version conflicts and need to be excluded. When you’ve gone through all the trouble of getting the dependencies out of the way, then you need to write web.xml, springMVC.xml configuration files, etc. We just want to write a Hello-word project, but we spend a lot of time on configuration files and JAR dependencies. Greatly affected the efficiency of our development, and increased the difficulty of Web development. SpringBoot was created to simplify this complex configuration and the conflicting dependencies of various versions. We now create a Springboot project through IDEA in minutes, you don’t need to worry about configuration (basically zero configuration), let you really implement out of the box. SpringBoot saves you a lot of time with your girlfriend. Why would a programmer have a girlfriend? Not only does it allow you to spend more time developing your business logic, but it also lowers the bar for Web development. So SpringBoot is a little bit more understanding of people’s clothing, err, err, understanding of developers’ pain points.
SpringBoot automatically loads the configuration
As useful as Springboot is, we as a user are curious to see how it works out of the box. Spring Boot has a global configuration file: application.properties or application.yml. In this global file, you can configure all kinds of parameters such as you want to change the port server.port or you want to change the log level. See the official website for more configurable properties. Docs. Spring. IO/spring – the boot…
So many attributes, how do these attributes work in the project? The SpringBoot project looks like it has no configuration “(except application.properties or application.yml), so if we can’t find a way through the configuration, we can only find a way through the boot class. The Boot class is just a bare main method, with only one annotation on it, SpringBootApplication, which is an essential annotation for SpringBoot projects. The principle of auto-configuration must have a lot to do with this annotation! Let’s take a look at this annotation. “@SpringBootApplication Annotation”
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@SpringBootConfiguration@EnableAutoConf iguration@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })public @interface SpringBootApplication {Copy the code
There is nothing to say about the top four annotations here. Basically, if you have implemented custom annotations, you know what they mean.
-
‘@springBootConfiguration’ inherits from ‘@Configuration’ and has the same function, marking the current class as a Configuration class.
-
@ComponentScan is used on a class or interface to specify a scan path, just like Xml configuration. ‘SpringBoot’ defaults to the path to boot the class if the scan path is not written.
-
`@EnableAutoConfiguration`
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoCo nfigurationImportSelector.class)public @interface EnableAutoConfiguration {
AutoConfigurationImportSelector under this note we focus on this class getCandidateConfigurations. This method through SpringFactoriesLoader loadFactoryNames () scans All jars with meta-INF/Spring. factories (spring.factories can be understood as spring Boot’s own SPI mechanism). Spring-boot-autoconfigure-x.x.jar contains a spring.factories file. The spring.factories files take the form of groups of Key = values, where one Key is the full class name of the EnableAutoConfiguration class and its value is a list of class names ending in AutoConfiguration, There are redis, MQ, etc. These class names are separated by commas.
We are back to getAutoConfigurationEntry this method when the execution of the getCandidateConfigurations this method we can see the loaded a total of 127 automatic configuration classes. Do all of these classes have to be loaded? Springboot is not that silly, it advocates loading on demand.
-
It gets rid of duplicate classes
-
Filter out we configure the ` exclude ` annotate the class the following configuration will filter out ` RestTemplateAutoConfiguration ` this class
-
After the above processing, the remaining auto-configured classes need to meet certain conditions if they are to work. When these conditions are met, ‘Spring Boot’ is implemented via conditional annotations.
❝
ConditionalOnBean ConditionalOnClass ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression ConditionalOnExpression Based on the SpEL expression is true as a judgment condition to instantiate
ConditionalOnJava: ConditionalOnJndi: ConditionalOnMissingBean: ConditionalOnMissingBean: ConditionalOnMissingBean: ConditionalOnJava: ConditionalOnJndi: ConditionalOnMissingBean: ConditionalOnMissingBean
@ ConditionalOnMissingClass: when the container is not specified in the class
@ ConditionalOnWebApplication: the current project is under the condition of the Web project
@ ConditionalOnNotWebApplication: under the condition of the current project is not the Web project
@ ConditionalOnProperty: specify the attributes for the specified value @ ConditionalOnResource: class path if there is a specified value @ ConditionalOnOnSingleCandidate: When the specified Bean has only one in the container, or more than one but specifies the preferred Bean
❞
These annotations are combined with the @Conditional annotation, except that the class to be instantiated is instantiated only when the Conditional annotation is true, otherwise the class is ignored and filtered. When we go back to the code we can see that after the conditional filtering we only have 23 auto-configuration classes that meet the criteria. Everything else is filtered because it doesn’t meet the conditional comment. If we want to know which auto-configuration classes are filtered, why they are filtered, which classes are loaded, etc. Spring Boot logs everything for us. It was very sweet. We can adjust the log level to DEBUG. And then we can see the following log which is partially captured here. There are four parts of logs:
-
If the condition ‘Positive matches’ :’ @Conditional ‘is true, the configuration class is loaded by the Spring container.
-
‘Negative matches:’ ‘@Conditional’ condition is false, configuration class is not loaded by Spring container.
-
‘Exclusions’ : We clarify the classes that do not need to be loaded. Such as in the above to start the class configuration of ` RestTemplateAutoConfiguration ` class
-
‘Unconditional classes’ : Auto-configure classes without any class-level conditions, that is, classes will always be loaded automatically.
Automatic configuration takes effect
ServletWebServerFactoryAutoConfiguration configuration class, for example, we explain how to effect in the global configuration file attributes, such as: Server port = 88, how work (of course not configuration will also have a default value, the default values from the org. Apache. Catalina. Startup. Tomcat).
// Mark it as Configuration class @configuration (proxyBeanMethods = false) @autoConfigureOrder (order.highest_precedence)// If there is a ServletRequest. The class will only take effect @ ConditionalOnClass (ServletRequest. Class) @ ConditionalOnWebApplication (type = the SERVLET) / / Inject the @ConfigurationProperties annotation class into the Spring container Bean. @EnableConfigurationProperties(ServerProperties.class)@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class, ServletWebServerFactoryConfiguration.EmbeddedTomcat.class, ServletWebServerFactoryConfiguration.EmbeddedJetty.class, ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })public class ServletWebServerFactoryAutoConfiguration {Copy the code
We can find EnableConfigurationProperties annotation configuration ServerProperties. Inside the class
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)public class ServerProperties { /** * Server HTTP port. */ private Integer port;
Copy the code
There is a comment on this class: @ ConfigurationProperties, What it does is bind properties from the configuration file to the corresponding bean (that is, map our application.properties server.port to ServerProperties) In the class the port attribute) and @ EnableConfigurationProperties this annotation is already binding properties of the bean (ServerProperties) injection into the spring container (equivalent to @ Component annotation). All properties that can be configured in a configuration file are encapsulated in the xxxxPropertites class, and any properties that can be configured in a configuration file can refer to the property class corresponding to a particular function. By now you should be able to answer the question at the beginning of the article.
❝
Spring Boot uses the @enableAutoConfiguration annotation to find and load all the auto-configuration classes in the meta-INF/Spring. factories configuration file. These AutoConfiguration classes are named after the AutoConfiguration end, which is actually a JavaConfig Spring container configuration class. It can use the class named after the Properties end to obtain the Properties configured in the global configuration file such as: Server.port, and the XxxxProperties class is bound to the corresponding properties in the global configuration file via the @ConfigurationProperties annotation.
❞
I found a picture on the Internet and basically explained the process of automatic assembly. Picture address
conclusion
-
The ‘SpringBoot’ launch loads a large number of auto-configured classes (via ‘SPI’) and then retains the required classes according to conditional annotations.
-
Let’s introduce a new component to see if springBoot is already provided by default.
-
‘SpringBoot’ basically implements’ zero configuration ‘and is out of the box. ! [](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/52597c31a0c34fbbaace15f61feffda7~tplv-k3u1fbpfcp-zoom-1.image)