How does Spring Boot auto-configuration work?
When we annotate an application class with @EnableAutoConfiguration or @SpringBootApplication, SpringBoot tries to guess what beans are needed and configure them. Automatic configuration is based on the application’s CLASspath and custom beans. For example, if the classpath containing the tomcat – embedded. Jar, automatically configure TomcatServletWebServerFactory Bean. As follows:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }}Copy the code
So how does Spring Boot’s auto-configuration work? Since the @SpringBootApplication annotation is also automatically configured via the @enableAutoConfiguration annotation, let’s look at the @EnableAutoConfiguration definition:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
......
}
Copy the code
The @enableAutoConfiguration definition is special only in these two annotations:
- @AutoConfigurationPackage
- @Import(AutoConfigurationImportSelector.class)
What does @autoConfigurationPackage do?
Let’s look at @autoConfigurationPackage, which is defined as follows:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}
Copy the code
For @ Import (AutoConfigurationPackages. The Registrar. The class), literally, into a Registrar, The Registrar has realized ImportBeanDefinitionRegistrar interface, will launch a class in package storage package for automatic configuration. As follows:
/ * * * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
* configuration.
*/
static class Registrar implements ImportBeanDefinitionRegistrar.DeterminableImports {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
register(registry, new PackageImport(metadata).getPackageName());
}
Copy the code
@ Import ({AutoConfigurationImportSelector. Class}) do?
Back to @ Import ({AutoConfigurationImportSelector. Class}), the main method is selectImports:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if(! isEnabled(annotationMetadata)) {return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
Copy the code
This method does two things:
- AutoConfigurationMetadataLoader. LoadMetadata (enclosing beanClassLoader), Load meta-INF /spring-autoconfigure-metadata.properties file and read the automatically configured META Data.
- GetAutoConfigurationEntry (autoConfigurationMetadata annotationMetadata), load the meta-inf/spring. Factories file, get all the automatic configuration classes.
The meta-inf/spring – autoconfigure – metadata. The properties:
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration.AutoConfigureAfter=org.springfra mework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration.Configuration= org.springframework.boot.autoconfigure.data.neo4j.Neo4jBookmarkManagementConfiguration.Configuration= org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration= org.springframework.boot.autoconfigure.kafka.KafkaAnnotationDrivenConfiguration.Configuration= org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration.ConditionalOnClass=org.influxdb.InfluxDB ......Copy the code
META-INF/spring.factories
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
......
Copy the code
All of these AutoConfiguration classes are components to add to the Spring container for automatic configuration.
An example describes the principle of automatic configuration
In the meta-INF /spring.factories file, you can see the Gson auto-configuration classes:
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
......
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
......
Copy the code
You can see META Data automatically configured by Gson in meta-INF /spring-autoconfigure-metadata.properties. Specify that automatic configuration of gson is enabled only when the classpath contains com.google.gson.gson:
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration.ConditionalOnClass=com.google.gson.Gson
Copy the code
For GsonAutoConfiguration, you can see @conditionalonClass (gson.class) corresponding to the Meta Data configuration, And @ EnableConfigurationProperties (GsonProperties. Class), is used to specify the Gson what configuration items can be configured in the file, such as application, yaml.
@Configuration
@ConditionalOnClass(Gson.class)
@EnableConfigurationProperties(GsonProperties.class)
public class GsonAutoConfiguration {... }Copy the code