springBoot study notes 2-a preliminary study on the principle of operation

copy notes from mad god original article addresses
we wrote before HelloSpringBoot, in the end is how to run it, Maven project, we usually explore from the pom.xml file;

pom.xml

Parent dependency
Among them, it mainly depends on a parent project, mainly managing the resource filtering and plug-ins of the project!

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

Click in and find that there is another parent dependency

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

Insert picture description here

This is the place to truly manage all dependent versions in the SpringBoot application, the version control center of SpringBoot;

In the future, we import dependencies by default without writing the version; but if the imported package is not managed in the dependency, you need to manually configure the version;

Starter spring-boot-starter


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

springboot-boot-starter-xxx: is the scene starter of spring-boot

spring-boot-starter-web: Help us import the components that the web module depends on for normal operation;

SpringBoot extracts all the functional scenarios into one starter (starter), only need to introduce these starters in the project, all related dependencies will be imported in, we will import what kind of function we want to use The scene starter is enough; we can also customize the starter in the future; check all the starters on the
official website

Main start class

After analyzing pom.xml, let's take a look at the default main startup class of this
startup class

//@SpringBootApplication 来标注一个主程序类
//说明这是一个Spring Boot应用
@SpringBootApplication
public class SpringbootApplication {
    
    

   public static void main(String[] args) {
    
    
     //以为是启动了一个方法,没想到启动了一个服务
      SpringApplication.run(SpringbootApplication.class, args);
   }
}

But a simple startup class is not simple! Let's analyze what these annotations do. The
@SpringBootApplication
function: Annotate a certain 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 note: you can see that there are many other notes above!


@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(//@CompontentScan 的作用是 扫描配置的包(TypeExcludeFilter,AutoConfigurationExcludeFilter) 并且剔除某些东西
    excludeFilters = {
    
    @Filter(
    type = FilterType.CUSTOM,
    classes = {
    
    TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {
    
    AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {
    
    
    // ......
}

@ComponentScan
this annotation is very important in Spring, it corresponds to the element in the XML configuration.

Function: Automatically scan and load qualified components or beans, and load the bean definition into the IOC container
@SpringBootConfiguration
Function: SpringBoot configuration class, marked on a certain class, indicating that this is a SpringBoot configuration class;

// Click in to get the following @Configuration
@Configuration //Used on SpringBootConFiguration, indicating that it is also a configuration class annotation
public @interface SpringBootConfiguration {}
-"Click in @Configuration

@Component //说明Configuration 也是spring的组件
 public @interface Configuration {}

The @Configuration here means that this is a configuration class, and the configuration class is the xml configuration file corresponding to Spring;

The @Component inside means that the startup class itself is just a component in Spring, responsible for starting the application!

Let's go back to the SpringBootApplication annotation and continue to look.
#91A8C7
Let's continue to enter this annotation to view
@EnableAutoConfiguration
@EnableAutoConfiguration: Turn on the automatic configuration function

In the past, we needed to configure things ourselves, but now SpringBoot can automatically configure it for us; @EnableAutoConfiguration tells SpringBoot to turn on the automatic configuration function, so that the automatic configuration can take effect;

Notes connection point into view:
@AutoConfigurationPackage: Automatic configuration package
Insert picture description here
@Target (ElementType.TYPE {})
@Retention (RetentionPolicy.RUNTIME)
@Documented
@ Inherited
This is four yuan notes, details View my blog comments and reflections
@Import ({Registrar.class})
public @interface AutoConfigurationPackage { } @import: Spring bottom annotation @import, import a component into the container

Registrar.class Function: Scan all components in the package where the main startup class is located and all sub-packages under the package to the Spring container;

After this analysis is over, go back to the previous step and continue to read

@EnableAutoConfiguration

@EnableAutoConfiguration: Turn on the automatic configuration function

In the past, we needed to configure things ourselves, but now SpringBoot can automatically configure it for us; @EnableAutoConfiguration tells SpringBoot to turn on the automatic configuration function, so that the automatic configuration can take effect;

Click into the comment to continue to view:
Insert picture description here

@AutoConfigurationPackage : automatic configuration package

Click into @AutoConfigurationPackage-》
@Import({Registrar.class})
public @interface AutoConfigurationPackage { } @import: Spring bottom annotation @import, import a component into the container

Registrar.class Function: Scan all components in the package where the main startup class is located and all sub-packages under the package to the Spring container;

After this analysis is over, go back to the previous step and continue to look at
@Import({AutoConfigurationImportSelector.class}): Import components to the container;

AutoConfigurationImportSelector: Automatically configure the import selector, so which component selectors will it import? We click to go to this category to see the source code:

1. There is such a method in this class


// 获得候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    
    
    //这里的getSpringFactoriesLoaderFactoryClass()方法
    //返回的就是我们最开始看的启动自动导入配置文件的注解类;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;
}

//上面的方法调用同类下的该方法
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
    
    
        return EnableAutoConfiguration.class;
    }

2. This method calls the static method of the SpringFactoriesLoader class again! We enter the loadFactoryNames() method of the SpringFactoriesLoader class


public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
    
    
    String factoryClassName = factoryClass.getName();
    //这里它又调用了 loadSpringFactories 方法
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

Insert picture description here
2. This method calls the static method of the SpringFactoriesLoader class again! We enter the loadFactoryNames() method of the SpringFactoriesLoader class


public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
    
    
    String factoryClassName = factoryClass.getName();
    //这里它又调用了 loadSpringFactories 方法
    return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

3. We continue to click to view the loadSpringFactories method

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
    
    
    //获得classLoader , 我们返回可以看到这里得到的就是EnableAutoConfiguration标注的类本身
    MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
    if (result != null) {
    
    
        return result;
    } else {
    
    
        try {
    
    
            //去获取一个资源 "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();

            //将读取到的资源遍历,封装成为一个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 appeared multiple times: spring.factories, search it
globally, spring.factories.
We opened spring.factories according to the source, and saw a lot of auto-configuration files; this is the source of auto-configuration!
Insert picture description here

WebMvcAutoConfiguration

We can find one in the above automatic configuration class to open it, such as: WebMvcAutoConfiguration
Insert picture description here

You can see that these are all JavaConfig configuration classes, and some Beans are injected. You can find some classes you know, and look at them to get familiar!

Therefore, the real implementation of automatic configuration is to search for all the META-INF/spring.factories configuration files from the classpath, and instantiate the configuration items under the corresponding org.springframework.boot.autoconfigure. package into corresponding annotations through reflection. The IOC container configuration class in the form of @Configuration JavaConfig, which is then aggregated into an instance and loaded into the IOC container.

in conclusion:

When SpringBoot starts, it obtains the value specified by EnableAutoConfiguration from META-INF/spring.factories under the classpath.

Import these values ​​into the container as the auto-configuration class, and the auto-configuration class will take effect, helping us with the auto-configuration work;

The entire J2EE overall solution and automatic configuration are in the jar package of springboot-autoconfigure;

It will import a lot of automatic configuration classes (xxxAutoConfiguration) into the container, that is, import all the components needed for this scenario into the container, and configure these components;

With the automatic configuration class, we can avoid the work of manually writing configuration injection functional components;

Now everyone should have a general understanding of the operating principle of SpringBoot, and we will deepen it again later!

SpringApplication

springboot main startup class

package com.zhou.springboot02config;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//标注这个类是springboot的应用
@SpringBootApplication
public class Springboot02ConfigApplication {
    
    

    public static void main(String[] args) {
    
    
        //将springboot应用启动
        SpringApplication.run(Springboot02ConfigApplication.class, args);
    }
}

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 to the initializers property

3. Find out all application listeners and set them to the listeners property

4. Infer and set the definition class of the main method, and find the main class that runs

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

Run method process analysis
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_44788518/article/details/114003513