Operation principle
For research purposes, we normally start with the parent project’s POM.xml.
pom.xml
The parent relies on spring-boot-starter-parent to manage resource filtering and plug-ins for the project
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5. RELEASE</version>
<relativePath/> <! -- lookup parent from repository -->
</parent>
Copy the code
< span style = “box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;”
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.5. RELEASE</version>
<relativePath>. /.. /spring-boot-dependencies</relativePath>
</parent>
Copy the code
Initiator: spring-boot-starter-xxx: indicates the springboot scenario initiator
Spring-boot-starter-web: imports web-dependent components
<dependency> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Copy the code
The main program
@SpringBootApplication
Springboot is a springboot application that is launched by running the mian method of this class.
@SpringBootApplication // This is a main application class, indicating that this is a SpringBoot application
public class Springboot01HelloworldApplication {
public static void main(String[] args) {
// instead of executing a method, a service is started.SpringApplication.run(Springboot01HelloworldApplication.class, args); }}Copy the code
Click @SpringBootApplication to continue research, you will find @SpringBootConfiguration, @EnableAutoConfiguration, @ComponentScan these three annotations
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} )
Copy the code
- @ComponentScan: Spring automatically scans packages
This we saw in the Spring configuration file is used to automatically scan and load qualified components or beans, and load the beans into the IOC container.
- @springBootConfiguration: configuration class for SpringBoot
The annotation on a class indicates that the class is the springBoot configuration class, in this case it indicates that the SpringBootApplication class is the SpringBoot configuration class.
If we go ahead and click @springBootConfiguration, we’ll see @Configuration
2.1@Configuration: Configuration class, used to configure Spring XML files
If we go ahead and click on @Configuration, we’ll see the @Component annotation.
2.2 @Component: Component, which indicates that the startup class itself is a Component that starts the application.
At this point, the @springBootConfiguration line, we’re done.
@EnableAutoConfiguration
: Enable automatic assembly and pass@EnableAutoConfiguration
To help us automatically configure what we needed to configure earlier.
We continue to point @ EnableAutoConfiguration in check, will find @ @ AutoConfigurationPackage and Import ({AutoConfigurationImportSelector. Class}) the two annotations.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<? >[] exclude()default {};
String[] excludeName() default {};
}
Copy the code
3.1@ AutoConfigurationPackage
Click through and the @import ({Registrar. Class}) annotation appears
3.1.1@import ({register.class}) : The spring underlying annotation imports a component into the container
Registrar. Class: Scan all the components in the main launcher package and any subpackages under that package into the Spring container.
So now we’re done with the at sign AutoConfigurationPackage line.
3.2 @ Import ({AutoConfigurationImportSelector. Class}) : give the container Import components
AutoConfigurationImportSelector. Class: automatic assembling imported selector.
Import selector analysis:
- Let’s click in
AutoConfigurationImportSelector.class
Explore the source code of this class,
- We click
getCandidateConfigurations
Further analysis
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
Copy the code
2.1 use the getSpringFactoriesLoaderFactoryClass () method, we see return to the beginning start the automatic configuration file annotation class EnableAutoConfiguration. Class
protectedClass<? > getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;
}
Copy the code
2.2 Found that it calls the static method of the SpringFactoriesLoader class. We click loadFactoryNames to loadFactoryNames().
public static List<String> loadFactoryNames(Class<? > factoryType,@Nullable ClassLoader classLoader) {
ClassLoader classLoaderToUse = classLoader;
if (classLoader == null) {
classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
}
String factoryTypeName = factoryType.getName();
return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList());
}
Copy the code
Check that it calls the loadSpringFactories() method again
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) {
Map<String, List<String>> result = (Map)cache.get(classLoader);
if(result ! =null) {
return result;
} else {
HashMap result = new HashMap();
try {
Enumeration urls = classLoader.getResources("META-INF/spring.factories");
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 factoryTypeName = ((String)entry.getKey()).trim(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); String[] var10 = factoryImplementationNames;int var11 = factoryImplementationNames.length;
for(int var12 = 0; var12 < var11; ++var12) {
String factoryImplementationName = var10[var12];
((List)result.computeIfAbsent(factoryTypeName, (key) -> {
return new ArrayList();
})).add(factoryImplementationName.trim());
}
}
}
result.replaceAll((factoryType, implementations) -> {
return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
});
cache.put(classLoader, result);
return result;
} catch (IOException var14) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var14); }}}Copy the code
Source code analysis:
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
Getting the classLoader, we return and you can see that what we got here is the EnableAutoConfiguration annotation class itselfEnumeration<URL> urls = classLoader ! = null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
Get a resource “meta-INF /spring.factories”while
Looping, the read resource is iterated, encapsulated as a Properties
Spring. Factories file
WebMvcAutoConfiguration
Let’s open one of the auto-configuration classes above, such as WebMvcAutoConfiguration
Are familiar configuration, so, realize automatic configuration from the classpath to search all the meta-inf/spring. Factories configuration files, and the corresponding org. Springframework. Boot. Autoconfigure. The Configuration items under the package are instantiated by reflection into the corresponding IOC container Configuration classes in JavaConfig form annotated with @Configuration, which are then aggregated into an instance and loaded into the IOC container.
conclusion
- SpringBoot gets the value specified by EnableAutoConfiguration from the META-INF/ Spring. factories in the classpath at startup
- Import these values into the container as auto-configuration classes, which take effect and help us with auto-configuration work.
- The entire J2EE solution and automatic configuration is in the Springboot-Autoconfigure JAR package;
- It imports a lot of auto-configuration classes (xxxAutoConfiguration) into the container, which is to import all the components needed for this scenario into the container and configure them;
- With the automatic configuration class, we do not need to manually write configuration injection function components;
The main start class
SpringApplication
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); }}Copy the code
Analysis:
- The entrance of the SpringbootApplication. Class: application parameters
- Args: command line parameter
- This method returns a
ConfigurableApplicationContext
object
SpringApplication does the following things:
- Determine whether the type of application is a normal project or a Web project
- Find and load all available initializers into the Initializers property
- Find all application listeners and set them to the Listeners properties
- Infer and set the definition class of the main method to find the running main class