Analysis of SpringBoot Auto-assembly Principle

Keywords: Java Spring Spring Boot

In springBoot, we don't need to do any configuration to write directly at the business level

Code, because springBoot Help US configure all the environments.

Here's a simple springboot Project Analysis

Project Code

springBoot main program
```java
@SpringBootApplication
public class HelloApplication {
    public static void main(String[] args) {
        SpringApplication.run(HelloApplication.class, args);
    }
}

Part of the code for the pom file

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.5.6</version>
  <relativePath/> <!-- lookup parent from repository -->
</parent>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Start by analyzing the pom file, each springBoot project will introduce a parent project, click into it, and find that there is also a parent project, spring-boot-dependencies, under which the project is dependent.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.5.6</version>
</parent>

Click Enter again and find that springBoot has declared for us the version number on which almost all development depends. When we introduce dependencies, we do not need to declare the version number. SpringBoot automatically chooses the version number for us.

<activemq.version>5.16.3</activemq.version>
<antlr2.version>2.7.7</antlr2.version>
<appengine-sdk.version>1.9.91</appengine-sdk.version>
<artemis.version>2.17.0</artemis.version>
<aspectj.version>1.9.7</aspectj.version>
<assertj.version>3.19.0</assertj.version>
<atomikos.version>4.0.6</atomikos.version>
<awaitility.version>4.0.3</awaitility.version>
<build-helper-maven-plugin.version>3.2.0</build-helper-maven-plugin.version>
<byte-buddy.version>1.10.22</byte-buddy.version>
<caffeine.version>2.9.2</caffeine.version>
......

Next, we analyze the dependencies we introduced
Official Documentation: Starters are a convenient set of dependency descriptors that you can include in your application. You can get a one-stop service of all the Spring and related technologies you need without searching for sample code and copying and pasting dependency descriptors for loading.

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>

By introducing this dependency, we are introducing all the web-related dependencies.

You can see that the introduction of spring-webmvc, spring-web, tomcat, json, starter.

After a brief analysis of the pom file, the next point is to analyze how the configuration will automatically complete the assembly while the project is running.

Analyzing the springBoot main program, we found a comment @SpringBootApplication labeled on the class from
As the name shows, the note indicates that this is a SpringBoot project.

Click Enter to discover that there are two more notes on this note, which you will analyze one by one

@SpringBootConfiguration
@EnableAutoConfiguration

By name, @springBootConfiguration is configuration related.
Click Enter again to find a @Configuration annotation under @springBootConfiguration indicating that our main program HelloApplication class is a configuration class.

Next, look at the second comment, @EnableAutoConfiguration, which, by name, serves to complete the automatically configured class.

Click in and find two notes on the note. Let's analyze them one by one

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

The @AutoConfiguration Package, known by name, automatically configures packages, specifying default package rules that automatically scan all packages in the package in which the main program HelloApplication class resides.

Let's click in and see how to do this

@Import({Registrar.class})

The purpose of this annotation is to load the Registrat class into a container.
Click Enter to see what this class does.

Found a method that registerBeanDefinitions registers defined bean objects

public void registerBeanDefinitions(AnnotationMetadata metadata, 
									BeanDefinitionRegistry registry) {
	AutoConfigurationPackages.register(registry, (String[])(new 
	AutoConfigurationPackages.PackageImports(metadata)).
	getPackageNames().toArray(new String[0]));
}

AnnotationMetadata metadata annotates the metadata of the class, which is the metadata of the main HelloApplication class
Breakpoint debugging, found (new AutoConfiguration Packages.PackageImports (metadata). getPackageNames()
The value of this expression is the package in which the HelloApplication class resides.

Add all the components under the package where the main program class HelloApplication is located to the container.
Now complete the role analysis of the @AutoConfiguration Package annotation.
@EnableAutoConfiguration also introduces a class @Import ({AutoConfiguration ImportSelector.class})

AutoConfiguration Import Selector automatically configures the import selector.

Point solution into this class, there is a method selectImports, select import

public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
        }
    }

This getAutoConfiguration Entry method automatically configures the loading method.
In this method, this line gets information about all the configurations to load.

 List<String> configurations = this.getCandidateConfigurations
 (annotationMetadata, attributes);


Enter the getCandidateConfigurations method

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;
}

In SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()); Loading completed.

Click into the SpringFactoriesLoader class and find

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

FACTORIES_ RESOURCE_ File path to LOCATION factory. This is the path to load the configuration file.
springBoot reads the configuration file information to load from the META-INF/spring.factories file.

This is the file below this package.

Open the file and find that it contains all the information you want to configure.

Of course, not all configuration classes are loaded.
Each auto-configuration class is loaded conditionally.
Conditional assembly rules (@Conditional) will eventually be configured as required.

 

Posted by sgs-techie on Thu, 04 Nov 2021 12:08:59 -0700