SpringBoot: A Preliminary Study of Operating Principles
How does Hello SpringBoot, which we wrote earlier, work? Maven projects, we usually start with the pom.xml file.
pom.xml
2.1, Parent Dependency In which it mainly depends on a parent project, mainly managing the project's resource filtering and plug-ins!
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.5.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
Click in and find that there is also a parent dependency
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.5.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
This is where you really manage all dependent versions in your SpringBoot application, SpringBoot's Version Control Center; later we import dependent versions by default and do not need to write versions; but if the imported packages are not managed in dependencies, you will need to configure versions manually;
2.2, Starter spring-boot-starter
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
Spring boot-boot-starter-xxx: the spring-boot scene launcher spring-boot-starter-web: helps us import the components on which the web module depends to function properly; SpringBoot pulls out all the functional scenes and makes them into a starter.All you need to do is to import these starters into your project, and all the related dependencies will be imported. You can import any scene launcher with whatever functionality you want; you can customize starters in the future; the main startup class parses pom.xml to see this startup class 2.3, the default main startup class/@SpringBootApplication to label a main program class
//Explain that this is a Spring Boot application
@SpringBootApplication public class SpringbootApplication { public static void main(String[] args) { //I thought I started a method, but I didn't expect to start a service SpringApplication.run(SpringbootApplication.class, args); } }
But a simple startup class is not easy! Let's analyze what these notes do.
2.4, @SpringBootApplication Role:
Label indicates in a class that this class is the main configuration class for SpringBoot, and SpringBoot should run the main method of this class to start SpringBoot applications; enter this annotation: you can see there are many other annotations above!
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan( excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = ), @Filter( type = FilterType.CUSTOM, classes = )} ) public @interface SpringBootApplication { // ...... }
2.5,@ComponentScan
This note is important in Spring.It corresponds to the elements in the XML configuration. Role: Automatically scan and load qualified components or beans, load this bean definition into IOC container 2.6, @SpringBootConfiguration Role: SpringBoot's configuration class, labeled on a class, indicating that this is a SpringBoot's configuration class; let's go on to this annotation to view//point to get the following
@Component @Configuration public @interface SpringBootConfiguration {} @Component public @interface Configuration {}
Here, @Configuration, indicates that this is a configuration class, which is the xml configuration file for Spring; the @Component inside indicates that the startup class itself is a component of Spring and is responsible for starting the application! Let's go back to the SpringBootApplication comment and continue.
2.7, @EnableAutoConfiguration@EnableAutoConfiguration: What we needed to configure ourselves before we turned on auto-configuration, but now SpringBoot can configure it for us automatically;
@EnableAutoConfiguration tell SpringBoot Turn on the auto-configuration function so that the auto-configuration will take effect; click on Notes to continue viewing:@AutoConfigurationPackage : Automatic Configuration Package@Import() public @interface AutoConfigurationPackage { } @import : Spring Bottom Notes@import , Import a component into a container Registrar.class Role: Scan the package of the main boot class and all components in all subpackages under the package to Spring Container; this analysis is complete, step back and continue looking@Import() : Import components to containers; AutoConfigurationImportSelector : Automatically configure the import selector, then which component selectors will it import? Let's click on this class to see the source code: 1. There is one such method in this class// Get candidate configurations protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //Here, the getSpringFactoriesLoaderFactoryClass() method //Return is the annotation class we first looked at to launch the auto-import profile; EnableAutoConfiguration 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; }
2. This method calls the static method of the SpringFactoriesLoader class again! We enter the SpringFactoriesLoader class loadFactoryNames() method
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); //Here it calls the loadSpringFactories method again return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList()); }
3. Let's continue clicking to view the loadSpringFactories method
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { //Obtaining the classLoader, we return to see that what we get here is the class itself labeled by EnableAutoConfiguration MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { //To get a resource "META-INF/spring.factories" Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); //Traverse the read resource and encapsulate it as a Properties 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; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
4. Found a file that appears many times: spring.factories, search it globally 2.8, spring.factories We open spring.factories from the source and see a lot of auto-configuring files; that's where auto-configuring comes from! WebMvcAutoConfiguration We look for any of the auto-configuring classes above, such as: WebMvcAutoConfiguration can see that each of these are JavaConfig configuration classes, and they are injected with some beans, so you can find some classes you know and get familiar with them! So, the real implementation of AutoConfiguration is to search all META-INF/spring.factories configuration files from the classpath and put the corresponding org.springframework.boot.autoconfigure.The configuration items under the package are instantiated by reflection into IOC container configuration classes corresponding to JavaConfig labeled @Configuration.These are then aggregated into an instance and loaded into the IOC container. Conclusion: SpringBoot takes the values specified by EnableAutoConfiguration from META-INF/spring.factories in the class path at startup and imports these values into the container as auto-configuration classes, which take effect.Help us with auto-configuration; the entire J2EE solution and auto-configuration is in the springboot-autoconfigure jar package; it imports a lot of auto-configuration classes (x xxxAutoConfiguration) into the container.It's all about importing and configuring all the components needed to import this scenario into the container; having an automatic configuration class saves us from manually writing configuration injection function components, and so on; now you should have a general idea of how SpringBoot works, and we'll go deeper later!
2.9. Not an easy way I thought I was running a main method, but I started a service unexpectedly.
@SpringBootApplication public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
The SpringApplication.run analysis analysis method is divided into two main parts, one is the instantiation of SpringApplication, the other is the execution of Run method; 2.10, SpringApplication class mainly do the following four things: 1, infer whether the type of application is a normal project or a Web project
2. Find and load all available initializers and set them in the initializers property
3. Find all application listeners and set them in the listeners property
4. Inform and set the definition class of the main method, find the running main class and view the constructor:
public SpringApplication(ResourceLoader resourceLoader, Class... primarySources) { // ...... this.webApplicationType = WebApplicationType.deduceFromClasspath(); this.setInitializers(this.getSpringFactoriesInstances(); this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = this.deduceMainApplicationClass(); }