Análisis de los principios básicos de la puesta en marcha de SpringBoot

pom.xml

Dependencia paterna

El proyecto principal depende principalmente de un proyecto principal, principalmente para administrar el filtrado de recursos y los complementos del proyecto.

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

Haga clic y descubra que hay otra dependencia de los padres


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <relativePath>../../spring-boot-dependencies</relativePath>
</parent>

Este es el lugar para administrar verdaderamente todas las versiones dependientes en la aplicación SpringBoot, el centro de control de versiones de SpringBoot;

En el futuro, importaremos dependencias por defecto sin escribir la versión, pero si el paquete importado no se administra en la dependencia, es necesario configurar manualmente la versión;

Lanzacohetes


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

springboot-boot-starter-xxx: es el iniciador de escena de spring-boot

spring-boot-starter-web: Ayúdanos a importar los componentes de los que depende el módulo web para su funcionamiento normal;

SpringBoot extrae todos los escenarios funcionales en un iniciador (iniciador), solo es necesario introducir estos iniciadores en el proyecto, se importarán todas las dependencias relacionadas, importaremos qué tipo de función queremos usar El iniciador de escena es suficiente; podemos también personalizamos el motor de arranque nosotros mismos en el futuro;

Clase de salida principal

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

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

}

@SpringBootApplication

Función: Anote una cierta clase para indicar que esta clase es la clase de configuración principal de SpringBoot, y SpringBoot debe ejecutar el método principal de esta clase para iniciar la aplicación SpringBoot;


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

@ComponenteScan

j corresponde al elemento en la configuración XML.

Función: escanee y cargue automáticamente componentes o beans calificados, y cargue esta definición de bean en el contenedor IOC

@SpringBootConfiguration

Función: La clase de configuración de SpringBoot, marcada en una determinada clase, indica que esta es una clase de configuración de SpringBoot;

Continuamos yendo a esta anotación para ver

// 点进去得到下面的 @Component
@Configuration
public @interface SpringBootConfiguration {
    
    }

@Component
public @interface Configuration {
    
    }

La @Configuration aquí significa que esta es una clase de configuración, y la clase de configuración es el archivo de configuración xml correspondiente a Spring ;

El @Component dentro significa que la clase de inicio en sí misma es solo un componente en Spring, ¡ responsable de iniciar la aplicación !

@EnableAutoConfiguration

@EnableAutoConfiguration le dice a SpringBoot que active la función de configuración automática, para que la configuración automática pueda tener efecto;
@AutoConfigurationPackage: paquete de configuración automática

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

@import: anotación inferior de Spring @import, importar un componente en el contenedor

Función Registrar.class: Escanea todos los componentes del paquete donde se encuentra la clase de inicio principal y todos los subpaquetes del paquete al contenedor Spring;

Una vez finalizado este análisis, vuelva al paso anterior y continúe leyendo

@Import ({AutoConfigurationImportSelector.class}): Importa componentes al contenedor;

AutoConfigurationImportSelector : configura automáticamente el selector de importación, entonces, ¿qué selectores de componentes importará? Hacemos clic para ir a esta categoría para ver el código fuente:

// 获得候选的配置
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;
}

Se llama a un método (un método estático de la clase SpringFactoriesLoader)

Método loadFactoryNames () de la clase SpringFactoriesLoader

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

loadSpringFactories 方法

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

Encontré un archivo que apareció varias veces: spring.factories

fábricas de primavera

Abra spring.factories y vea muchos archivos de configuración automática; ¡esta es la raíz de la configuración automática!

Por lo tanto, la implementación real de la configuración automática es buscar todos los archivos de configuración META-INF / spring.factories desde la ruta de clase y crear una instancia de los elementos de configuración en el paquete org.springframework.boot.autoconfigure. Correspondiente en las anotaciones correspondientes mediante la reflexión. La clase de configuración del contenedor IOC en forma de @Configuration JavaConfig, que luego se agrega a una instancia y se carga en el contenedor IOC.

para resumir

  1. Cuando SpringBoot se inicia, obtiene el valor especificado por EnableAutoConfiguration de META-INF / spring.factories en la ruta de clase.

  2. Importe estos valores al contenedor como la clase de autoconfiguración, y la clase de autoconfiguración entrará en vigencia, ayudándonos con el trabajo de autoconfiguración;

  3. Toda la solución general de J2EE y la configuración automática se encuentran en el paquete jar de springboot-autoconfigure;

  4. Importará muchas clases de configuración automática (xxxAutoConfiguration) al contenedor, es decir, importará todos los componentes necesarios para este escenario en el contenedor y configurará estos componentes;

Con la clase de configuración automática, podemos evitar el trabajo de escribir manualmente componentes funcionales de inyección de configuración;

Clase SpringApplication


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

Análisis SpringApplication.run

El análisis de este método se divide principalmente en dos partes, una es la instanciación de SpringApplication y la otra es la ejecución del método de ejecución;

Esta clase hace principalmente las siguientes cuatro cosas:

1. Deduzca si el tipo de aplicación es un proyecto normal o un proyecto web.

2. Busque y cargue todos los inicializadores disponibles y configúrelos en la propiedad de inicializadores

3. Descubra todos los escuchas de la aplicación y configúrelos en la propiedad de escuchas

4. Deduzca y establezca la clase de definición del método principal y busque la clase principal que se ejecuta

1. Ver el 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();
}

2. Ejecutar el análisis del proceso del método

Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/david2000999/article/details/114479288
Recomendado
Clasificación