Un artículo de 9000 palabras lo lleva a comprender el proceso de inicio de SpringBoot, el proceso de inicio de SpringBoot más detallado de la historia, con imágenes y textos.

inserte la descripción de la imagen aquí
De la tortura del alma del entrevistador desde lo más profundo de la auditoría interna: “Cuéntame sobre el proceso de arranque de springboot”; el
entrevistador con cara de confusión: “Simplifica la configuración de spring, principalmente porque tiene la función de montaje automático, y puede comenzar directamente, porque tiene un contenedor tomcat incrustado";
entrevistador: "Bueno, sí, estos son algunos de sus conceptos, aún no ha respondido mi pregunta, cómo comenzó y qué pasó cuando fue comenzó?";
Entrevistador confundido: "Ah~~~ No sé... Soy muy hábil en usarlo, ¡pero no sé qué hace en él!"; Entrevistador: "
Comprender el principio interno es para ayudarnos a expandirnos y al mismo tiempo verificar la capacidad de aprendizaje de una persona, si desea llevar su carrera profesional al siguiente nivel, debe conocer estas cosas de bajo nivel, está bien, regrese y espere las noticias. Entrevistador
: ↓
inserte la descripción de la imagen aquí

¿Qué es Spring Boot?

Springboot depende de Spring. En comparación con Spring, además de tener todas las funciones de Spring, Springboot no necesita una configuración xml engorrosa, que depende de su propia función potente de ensamblaje automático; y tiene integrados Tomcat, Jetty y otros contenedores web, springmvc integrado permite que springboot se ejecute directamente sin contenedores adicionales y proporciona algunas características no funcionales comunes en proyectos a gran escala, como servidores integrados, seguridad, indicadores, detección de salud, configuración externa, etc.

De hecho, todo el mundo sabe que spring, boot significa arranque. Por lo tanto spring boot es en realidad una herramienta para iniciar un proyecto spring, en una palabra spring boot es un framework que sirve al framework, también se puede decir que spring boot es una herramienta que simplifica la configuración de spring;

Características principales de Spring Boot

1. Proyecto Spring que puede ejecutarse de forma independiente: Spring Boot puede ejecutarse de forma independiente en forma de un paquete jar.

2. Contenedor de servlet integrado: Spring Boot puede optar por integrar Tomcat, Jetty o Undertow, y no es necesario implementar proyectos en forma de paquetes de guerra.

3. Configuración simplificada de Maven: Spring proporciona archivos POM básicos recomendados para simplificar la configuración de Maven.

4. Configurar Spring automáticamente: Spring Boot configurará automáticamente Spring Framework de acuerdo con las dependencias del proyecto, lo que reduce en gran medida la configuración que utilizará el proyecto.

5. Proporcione funciones listas para producción: Proporcione funciones que se puedan usar directamente en el entorno de producción, como indicadores de rendimiento, información de la aplicación y comprobaciones del estado de la aplicación.

6. Sin generación de código y configuración xml: Spring Boot no genera código. Todas las configuraciones de Spring se pueden realizar sin ninguna configuración xml.

Proceso de inicio de SpringBoot

El inicio de springboot ha pasado por una serie de procesos. Echemos un vistazo al diagrama de flujo del proceso general. No me digas,
inserte la descripción de la imagen aquí
hay muchos pasos, pero no importa. Para ayudar que todos entiendan, los números anteriores se explicarán uno por uno de manera popular, dígales a todos de una manera fácil de entender, lo que se ha hecho adentro, no diga tonterías y comience todo el proceso.

1. Ejecute el método SpringApplication.run()

Sin duda, todas las aplicaciones Springboot estándar comienzan desde el método de ejecución

package com.spring;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
 
@SpringBootApplication
public class App  {
    
    
 
    public static void main(String[] args) {
    
    
        // 启动springboot
        ConfigurableApplicationContext run = SpringApplication.run(App.class, args);
    }
 
}

Después de ingresar el método de ejecución, se creará un nuevo objeto SpringApplication, y el constructor que crea este objeto ha realizado algunos trabajos preparatorios. Los pasos 2 a 5 del número son lo que se realiza en el constructor.

	/**
	 * Static helper that can be used to run a {@link SpringApplication} from the
	 * specified sources using default settings and user supplied arguments.
	 * @param primarySources the primary sources to load
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return the running {@link ApplicationContext}
	 */
	public static ConfigurableApplicationContext run(Class<?>[] primarySources,
			String[] args) {
    
    
		return new SpringApplication(primarySources).run(args);
	}

Además, déjame explicarte que hay tres formas de iniciar SpringBoot. Para conocer otros métodos de inicio, consulta mi otra publicación: Tres formas de iniciar SpringBoot.

2. Determinar el tipo de aplicación

En el método de construcción de SpringApplication, en primer lugar, se usará el método WebApplicationType.deduceFromClasspath() para evaluar el contenedor de la aplicación actual, y el contenedor Servlet se usa de manera predeterminada. Además del servlet, hay NONE y REACTIVE (programación receptiva). );
inserte la descripción de la imagen aquí

3. Cargue todos los inicializadores

El inicializador cargado aquí es el propio inicializador de springboot, que se carga desde el archivo de configuración META-INF/spring.factories, entonces, ¿dónde está este archivo? Hay 2 de ellos. Hay un
inserte la descripción de la imagen aquí
archivo spring.factories en el proyecto spring-boot-autoconfigure y el proyecto spring-boot del paquete jar del código fuente. Puede ver que la interfaz al principio es org.springframework.context .ApplicationContextInitializer es el inicializador.
inserte la descripción de la imagen aquí
Por supuesto, también podemos implementar un inicializador personalizado nosotros mismos: implementar la interfaz ApplicationContextInitializer

MiAplicaciónContextInitializer.java

package com.spring.application;
 
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
/**
 * 自定义的初始化器
 */
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    
    
    @Override
    public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
    
    
        System.out.println("我是初始化的 MyApplicationContextInitializer...");
    }
}

Agregue el archivo de configuración META-INF/spring.factories en el directorio de recursos, el contenido es el siguiente y registre el inicializador personalizado;

org.springframework.context.ApplicationContextInitializer=\
com.spring.application.MyApplicationContextInitializer

inserte la descripción de la imagen aquí
Luego de iniciar springboot se puede ver el contenido impreso en la consola, aquí podemos ver intuitivamente su secuencia de ejecución, la cual se ejecuta luego de imprimir el banner;
inserte la descripción de la imagen aquí

4. Cargar todos los oyentes

La carga del oyente también se carga desde el archivo de configuración META-INF/spring.factories. A diferencia de la inicialización, el oyente carga una clase que implementa la interfaz ApplicationListener. El
inserte la descripción de la imagen aquí
oyente personalizado también es el mismo que el inicializador. Está bien, no lo estoy voy a dar un ejemplo aquí;

5. Configure la clase principal del programa para que se ejecute

deduceMainApplicationClass(); Este método es solo para encontrar la clase donde se encuentra el método principal, en preparación para el análisis posterior del paquete, deducir significa inferir, por lo que para ser precisos, la función de este método es inferir la clase donde se encuentra el método principal. se encuentra el método;
inserte la descripción de la imagen aquí

6. Inicie el temporizador

Cuando el programa se ejecuta aquí, ha ingresado al cuerpo principal del método de ejecución. El método de ejecución llamado en el primer paso es un método estático. En ese momento, el objeto SpringApplication no ha sido instanciado. El método de ejecución llamado ahora no es estático y necesita ser instanciado. Se puede llamar. Después de ingresar, el temporizador se iniciará primero. ¿Cuál es la función de este temporizador? Como su nombre lo indica, se utiliza para medir el tiempo y calcula cuánto tarda en iniciarse Springboot; el código clave es el siguiente:

// 实例化计时器
StopWatch stopWatch = new StopWatch(); 
// 开始计时
stopWatch.start();

Captura de pantalla del segmento de código del método de ejecución
inserte la descripción de la imagen aquí

7. Establezca java.awt.headless en verdadero

Aquí java.awt.headless se establece en verdadero, lo que significa que se ejecuta en el lado del servidor y aún puede funcionar en el modo sin monitor, mouse y teclado, simulando la función de los dispositivos de entrada y salida.

Después de realizar tal operación, ¿qué quiere hacer SpringBoot? De hecho, quiero configurar la aplicación para permitir que se inicie incluso si no se detecta la pantalla. Para el servidor, no hay necesidad de una pantalla, por lo que debería establecerse así.

El cuerpo del método es el siguiente:

	private void configureHeadlessProperty() {
    
    
		System.setProperty(SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, System.getProperty(
				SYSTEM_PROPERTY_JAVA_AWT_HEADLESS, Boolean.toString(this.headless)));
	}

A través del método, podemos ver que hay otro getProperty() en el método setProperty(), ¿no es esto innecesario? De hecho, hay 2 parámetros en el método getProperty(), el primer valor clave y el segundo es el valor predeterminado, lo que significa encontrar el valor de la propiedad a través del valor clave. Si el valor de la propiedad está vacío, el valor predeterminado es verdadero. será devuelto, se garantiza que debe haber un caso de valor;

8. Obtenga y habilite el oyente

Este paso implementa la operación básica de inicialización a través del oyente. Este paso hace 2 cosas

  1. Crea todos los oyentes Spring Run y ​​publica los eventos de inicio de la aplicación
  2. habilitar oyente
    inserte la descripción de la imagen aquí

9. Establecer los parámetros de la aplicación

Encapsule los parámetros pasados ​​al ejecutar el método de ejecución en un objeto
inserte la descripción de la imagen aquí
Simplemente encapsule los parámetros en un objeto, no hay nada que decir, el constructor del objeto es el siguiente

	public DefaultApplicationArguments(String[] args) {
    
    
		Assert.notNull(args, "Args must not be null");
		this.source = new Source(args);
		this.args = args;
	}

Entonces la pregunta es, ¿de dónde viene este parámetro? De hecho, es el parámetro que se pasa al ejecutar el método de ejecución estático en el método principal.
inserte la descripción de la imagen aquí

10. Prepara las variables de entorno

Prepare las variables de entorno, incluidas las propiedades del sistema y las propiedades configuradas por el usuario. El bloque de código ejecutado se puede ver después de romper un punto de interrupción en el método prepareEnvironment inserte la descripción de la imagen aquí
. Carga las variables de entorno maven y del sistema.
inserte la descripción de la imagen aquí

11. Ignora la información del frijol

Este método configureIgnoreBeanInfo() Este método es establecer el valor predeterminado de spring.beaninfo.ignore en verdadero, lo que significa omitir la búsqueda de beanInfo, y el principio de establecer el valor predeterminado es el mismo que en el paso 7;

    private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
    
    
		if (System.getProperty(
				CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
    
    
			Boolean ignore = environment.getProperty("spring.beaninfo.ignore",
					Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME,
					ignore.toString());
		}
	}

Por supuesto, también puede agregar la siguiente configuración al archivo de configuración para configurarlo como falso

spring.beaninfo.ignore=false

Todavía no conozco la función específica de esta configuración, y la agregaré después de que el autor se entere.

12. Imprimir información de banner

Obviamente, este proceso se usa para imprimir el gran banner de primavera en la consola, que es lo siguiente: ¿
inserte la descripción de la imagen aquí
Dónde lo imprimió? Lo imprimió en SpringBootBanner.java.Esta clase implementa la interfaz Banner.

Y la información del banner está escrita directamente en el código;
inserte la descripción de la imagen aquí
a algunas empresas les gusta personalizar la información del banner, ¿qué debo hacer si quiero cambiarlo a mi ícono favorito? En realidad es muy simple, solo agregue un banner.txt en los recursos. directorio El contenido del archivo txt es el siguiente

                 _           _
                (_)         | |
 _   _  _____  ___ _ __   __| | ___  _ __   __ _
| | | |/ _ \ \/ / | '_ \ / _` |/ _ \| '_ \ / _` |
| |_| |  __/>  <| | | | | (_| | (_) | | | | (_| |
 \__, |\___/_/\_\_|_| |_|\__,_|\___/|_| |_|\__, |
  __/ |                                     __/ |
 |___/                                     |___/
:: yexindong::

Asegúrese de agregarlo al directorio de recursos, no lo agregue mal
inserte la descripción de la imagen aquí
, solo necesita agregar un archivo y no necesita hacer nada más, luego inicie Springboot directamente y podrá ver el efecto.
inserte la descripción de la imagen aquí

13. Crea el contexto de la aplicación

Cree una instancia del contexto de la aplicación, llame al método createApplicationContext(), aquí hay que usar la reflexión para crear objetos, no hay nada que decir;
inserte la descripción de la imagen aquí

14. Crear una instancia del reportero de excepción

El reportero de excepciones se usa para capturar excepciones globales. Cuando ocurre una excepción en la aplicación springboot, el reportero de excepciones la capturará y la manejará en consecuencia. El reportero de excepciones predeterminado está configurado en el archivo spring.factories.

inserte la descripción de la imagen aquí
Cabe señalar que este informador de excepciones solo detectará la excepción lanzada durante el proceso de inicio. Si se informa un error en la solicitud del usuario después de que se complete el inicio, el informador de excepciones no detectará la excepción que se produce en la solicitud. Ahora que entiendes el principio,
inserte la descripción de la imagen aquí
a continuación configuramos un reportero de excepción para jugar con nosotros mismos;

MyExceptionReporter.java hereda la interfaz SpringBootExceptionReporter

package com.spring.application;
 
import org.springframework.boot.SpringBootExceptionReporter;
import org.springframework.context.ConfigurableApplicationContext;
 
public class MyExceptionReporter implements SpringBootExceptionReporter {
    
    
 
 
    private ConfigurableApplicationContext context;
    // 必须要有一个有参的构造函数,否则启动会报错
    MyExceptionReporter(ConfigurableApplicationContext context) {
    
    
        this.context = context;
    }
 
    @Override
    public boolean reportException(Throwable failure) {
    
    
        System.out.println("进入异常报告器");
        failure.printStackTrace();
        // 返回false会打印详细springboot错误信息,返回true则只打印异常信息 
        return false;
    }
}

Registre el reportero de excepciones en el archivo spring.factories

# Error Reporters 异常报告器
org.springframework.boot.SpringBootExceptionReporter=\
com.spring.application.MyExceptionReporter

inserte la descripción de la imagen aquí
Luego configuramos el número de puerto en un valor grande en application.yml, lo que definitivamente causará un error.

server:
  port: 80828888

Después del inicio, la consola imprime la siguiente imagen
inserte la descripción de la imagen aquí

15. Prepara el contexto

El entorno de contexto preparado aquí es para prepararse para la próxima actualización, y se realizan algunas cosas adicionales en él;
inserte la descripción de la imagen aquí

15.1 Generador BeanName para instanciar singletons

Dentro del método postProcessApplicationContext(context); El objeto BeanNameGenerator se crea utilizando el modo singleton, que en realidad es el generador beanName utilizado para generar el nombre del objeto bean.

15.2 Ejecutar el método de inicialización

¿Cuáles son los métodos de inicialización? ¿Recuerdas el inicializador cargado en el paso 3? De hecho, todos los inicializadores cargados en el paso 3 se ejecutan y la clase que implementa la interfaz ApplicationContextInitializer

15.3 Registrar parámetros de inicio en el contenedor

Aquí, los parámetros de inicio se registran en el contenedor en modo singleton para conveniencia futura.El beanName del parámetro es: springApplicationArguments

16. Actualizar el contexto

La actualización del contexto ya se encuentra en la categoría de resorte. El ensamblaje automático y el inicio de Tomcat se completan en este método. Hay otros mecanismos integrados en resorte que no se detallarán aquí.
inserte la descripción de la imagen aquí

17. Posprocesamiento del contexto de actualización

El método afterRefresh es un procesamiento posterior al inicio, que está reservado para la expansión del usuario. Actualmente, este método está vacío.

/**
	 * Called after the context has been refreshed.
	 * @param context the application context
	 * @param args the application arguments
	 */
	protected void afterRefresh(ConfigurableApplicationContext context,
			ApplicationArguments args) {
    
    
	}

18. Fin del temporizador

En este punto, Springboot realmente se ha completado y el temporizador imprimirá la hora para iniciar Springboot.El
inserte la descripción de la imagen aquí
inicio sigue siendo muy rápido como se ve en la consola, y el inicio se completa en menos de 2 segundos;
inserte la descripción de la imagen aquí

19. Publicar evento listo para el contexto

Dile a la aplicación que estoy listo para ir a trabajar
inserte la descripción de la imagen aquí

20. Ejecutar un método de ejecución personalizado

Esta es una función de extensión, callRunners(context, applicationArguments) puede ejecutar un método de ejecución personalizado después de que se complete el inicio; hay 2 formas de lograrlo:

  1. Implementar la interfaz ApplicationRunner
  2. Implementar la interfaz CommandLineRunner

A continuación, verifiquemos que, para facilitar la legibilidad del código, puse estos dos métodos en la misma clase

package com.spring.init;
 
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
 
/**
 * 自定义run方法的2种方式
 */
@Component
public class MyRunner implements ApplicationRunner, CommandLineRunner {
    
    
 
    @Override
    public void run(ApplicationArguments args) throws Exception {
    
    
        System.out.println(" 我是自定义的run方法1,实现 ApplicationRunner 接口既可运行"        );
    }
 
    @Override
    public void run(String... args) throws Exception {
    
    
        System.out.println(" 我是自定义的run方法2,实现 CommandLineRunner 接口既可运行"        );
    }
}

Después de iniciar springboot, puede ver la información impresa en la consola
inserte la descripción de la imagen aquí

encima

De hecho, es bueno que los desarrolladores entiendan el principio del inicio de springboot. Al menos sabes qué se puede expandir, cómo expandir y cómo son sus principios internos. Creo que después de comprender estas ideas, déjate escribir un springboot tú mismo. También es posible, pero aquí hay solo una lista del proceso de inicio, no todos los involucrados, el código fuente es muy complicado, recuerdo que una vaca grande dijo: "Cuando miramos el código fuente, solo podemos adivinar cuál es el autor piensa por asociación o, y tenga cuidado de verificar, al igual que cuando aprendimos poemas antiguos cuando éramos jóvenes, solo podemos adivinar los pensamientos de los antiguos.Tomando el Tao Te King como ejemplo, todos tienen opiniones diferentes después de leerlo , que requiere opiniones diferentes”;

Supongo que te gusta

Origin blog.csdn.net/weixin_44947701/article/details/124055713
Recomendado
Clasificación