Preliminary study on operation principle

Keywords: Java Spring Spring Boot

Preliminary study on principle

pom.xml

Parent dependency

It mainly depends on a parent project, which mainly manages the resource filtering and plug-ins of 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>

Click in and find another 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 the place to really manage all dependent versions in the SpringBoot application, the SpringBoot version control center
In the future, we will import dependency. By default, we don't need to write a version; However, if the imported package is not managed in the dependency, you need to manually configure the version

Launcher spring boot starter

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

Springboot boot starter XXX: the scenario initiator of spring boot

Spring boot starter Web: it helps us import the components that the web module depends on for normal operation;

SpringBoot extracts all functional scenarios and makes them into starters. You only need to introduce these starters into the project, and all related dependencies will be imported. We can import the scenario starters with what functions we want to use; We can also customize the starter ourselves in the future

Main startup class


Some notes

@SpringBoot application (function: mark a class to indicate that this class is the main configuration class of SpringBoot, and SpringBoot should run the main method of this class to start the SpringBoot application)

Enter this annotation: you can see that there are many other annotations above!

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    // ......
}

@Componentscan (function: automatically scan and load qualified components or beans, and load the bean definition into the IOC container)

This annotation is important in Spring and corresponds to the elements in the XML configuration.

@SpringBoot configuration (function: the configuration class of SpringBoot is marked on a class to indicate that it is a SpringBoot configuration class)

// Click in to get the following @ Component
@Configuration
public @interface SpringBootConfiguration {}

@Component
public @interface Configuration {}

The @ Configuration here indicates that this is a Configuration class, which is the xml Configuration file corresponding to Spring;

The @ Component inside shows that the startup class itself is just a Component in Spring and is responsible for starting the application!

Let's go back to the spring boot application annotation and continue.

@Enable autoconfiguration

Previously, we needed to configure things ourselves, but now SpringBoot can automatically configure them for us@ EnableAutoConfiguration tells SpringBoot to enable the auto configuration function so that the auto configuration can take effect;
@AutoConfigurationPackage: autoconfiguration package

@Import({Registrar.class})
public @interface AutoConfigurationPackage {
}

@Import: the Spring underlying annotation @ import imports a component into the container

Function of Registrar.class: scan the package of the main startup class and all components in all sub packages under the package to the Spring container;

This analysis is finished. Step back and continue to look

@Import({AutoConfigurationImportSelector.class}): import components to the container

AutoConfigurationImportSelector: if the import selector is automatically configured, which component selectors will it import? Let's click this class to see the source code:
1. There is one such method in this class

// Obtain candidate configurations
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    //The getSpringFactoriesLoaderFactoryClass () method here
    //The returned annotation class is the annotation class that we first saw to start the automatic import configuration file; 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 also calls the static method of the springfactoryesloader class! We enter the loadFactoryNames() method of the springfactoryesloader class

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 to click to view the loadSpringFactories method

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    //After obtaining the classLoader, we can see that what we get here is the class itself marked with EnableAutoConfiguration
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
        return result;
    } else {
        try {
            //Go 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 resources and encapsulate them into a property
            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. Find a file that appears many times: spring.factories. Search it globally

spring.factories

We open spring.factories according to the source and see many automatic configuration files; This is the root of automatic configuration!

The real implementation of automatic Configuration is to search all META-INF/spring.factories Configuration files from the classpath, and instantiate the Configuration items under the corresponding org.springframework.boot.autoconfigure. Package into IOC container Configuration classes in the form of JavaConfig marked with @ Configuration through reflection, and then summarize them into an instance and load them into the IOC container.

Conclusion:

1. When springboot starts, obtain the value specified by EnableAutoConfiguration from META-INF/spring.factories under the classpath

2. Import these values into the container as an automatic configuration class, and the automatic configuration class will take effect to help us with automatic configuration;

3. The whole J2EE solution and automatic configuration are in the jar package of springboot autoconfigure;

4. It will import many automatic configuration classes (xxxAutoConfiguration) into the container, that is, import all components required for this scenario into the container and configure these components;

5. The automatic configuration class eliminates the need to manually write configuration injection function components;

SpringApplication

@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

SpringApplication.run analysis
One is the instantiation of spring application, and the other is the execution of run method

SpringApplication

This class mainly does 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 and load all available initializers and set them in the initializers property

4. Infer and set the definition class of the main method, and find the main class to run

View 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();
}

Posted by adwfun on Tue, 14 Sep 2021 14:15:44 -0700