Además de los eventos habituales de Spring Framework, como ContextRefreshedEvent, SpringApplication envía algunos eventos de aplicación adicionales.

Algunos eventos en realidad se activan antes de que se cree ApplicationContext, por lo que no puede registrar un oyente para estos eventos como una anotación @Bean. Puede registrarlos usando SpringApplication.addListeners(…​) o el método SpringApplicationBuilder.listeners(…​).

Si necesita que estos oyentes estén registrados automáticamente, independientemente de cómo se creó la aplicación, puede agregar el archivo META-INF/spring.factories al proyecto y hacer referencia a los oyentes usando clave org.springframework.context.ApplicationListener, como se muestra en el siguiente ejemplo:

org.springframework.context.ApplicationListener=com.example.project.MyListener

Los eventos de la aplicación se envían en el siguiente orden a medida que se ejecuta la aplicación:

  1. El evento ApplicationStartingEvent se envía al inicio de la ejecución, pero antes de que comience cualquier procesamiento que no sea el registro de escuchas e inicializadores.

  2. El evento ApplicationEnvironmentPreparedEvent se envía cuando se conoce el Environment que se utilizará en el contexto, pero antes de que se cree el contexto.

  3. El ApplicationContextInitializedEvent se distribuye cuando se prepara el ApplicationContext y se llama a ApplicationContextInitializers, pero antes de que se carguen las definiciones de bean.

  4. El evento ApplicationPreparedEvent se envía inmediatamente antes del inicio de la actualización, pero después de que se hayan cargado las definiciones de bean.

  5. El evento ApplicationStartedEvent se envía después de que se actualiza el contexto, pero antes de que se invoquen todas las líneas de herramientas de ejecución de comandos y aplicaciones.

  6. Inmediatamente después de esto, se envía un el evento AvailabilityChangeEvent se envía con LivenessState.CORRECT para indicar que se considera que la aplicación se está ejecutando.

  7. El evento ApplicationReadyEvent se envía después de invocar cualquier aplicación y ejecutor de línea de comando.

  8. Inmediatamente después, AvailabilityChangeEvent se envía con ReadinessState.ACCEPTING_TRAFFIC para indicar que la aplicación está lista para procesar solicitudes.

  9. El evento ApplicationFailedEvent se envía si se produce una excepción al inicio.

La lista anterior solo incluye eventos SpringApplicationEvent que están vinculados a SpringApplication. Además de estos, los siguientes eventos también se publican después de ApplicationPreparedEvent y antes de ApplicationStartedEvent:

  • WebServerInitializedEvent Evento enviado cuando WebServer está listo. ServletWebServerInitializedEvent y ReactiveWebServerInitializedEvent son variantes de servlet y servidor reactivo respectivamente.

  • El evento ContextRefreshedEvent se envía, si ApplicationContext está actualizado.

A menudo no es necesario Utilice los eventos de la aplicación, pero puede resultar útil tener en cuenta su existencia. Internamente, Spring Boot utiliza eventos para realizar diversas tareas.
Los detectores de eventos no tienen que realizar tareas potencialmente de larga duración porque se ejecutan en un solo subproceso por defecto. En su lugar, considere utilizar las herramientas de ejecución de la línea de comandos y de la aplicación.

Los eventos de la aplicación se envían utilizando el mecanismo de publicación de eventos de Spring Framework. Parte de este mecanismo garantiza que un evento publicado para los oyentes en un contexto secundario también se publicará para los oyentes en cualquier contexto ancestro. Por lo tanto, si su aplicación utiliza una jerarquía de instancias de SpringApplication, un oyente puede recibir múltiples instancias del mismo tipo de evento de aplicación.

Para que un oyente pueda distinguir un evento por su contexto de un evento para un contexto secundario, debe solicitar que se inyecte el contexto de su aplicación y luego comparar el contexto inyectado con el contexto del evento. El contexto se puede inyectar implementando ApplicationContextAware o, si el oyente es un bean, usando la anotación @Autowired.

Entorno web

SpringApplication intenta crear el tipo ApplicationContext deseado según lo especifique. El siguiente algoritmo se utiliza para determinar WebApplicationType:

  • Si Spring MVC está presente, AnnotationConfigServletWebServerApplicationContext

  • se usa Si Spring MVC no está presente y Spring WebFlux está presente, AnnotationConfigReactiveWebServerApplicationContext

  • De lo contrario, AnnotationConfigApplicationContext se usa

Esto significa que si usa Spring MVC y el nuevo WebClient de Spring WebFlux en la misma aplicación, Spring MVC será utilizado por defecto. Puedes anular esto fácilmente llamando a setWebApplicationType(WebApplicationType).

También puedes controlar completamente qué tipo de ApplicationContext se utiliza llamando a setApplicationContextClass(…​).

A menudo es deseable llamar a setWebApplicationType(WebApplicationType.NONE) cuando se usa SpringApplication en una prueba JUnit.

Acceso a los argumentos de la aplicación

Si necesita acceder a los argumentos de la aplicación que se pasaron a SpringApplication.run(…​), puede implementar el bean org.springframework.boot.ApplicationArguments. La interfaz ApplicationArguments proporciona acceso tanto a argumentos String[] sin procesar como a argumentos option y non-option analizados, como se muestra en el siguiente ejemplo:

Java

import java.util.List;
import org.springframework.boot.ApplicationArguments;
import org.springframework.stereotype.Component;
@Component
public class MyBean {
    public MyBean(ApplicationArguments args) {
        boolean debug = args.containsOption("debug");
        List<String> files = args.getNonOptionArgs();
        if (debug) {
            System.out.println(files);
        }
        // si se ejecuta con la opción "--debug logfile.txt" option, ["logfile.txt"] will be output.
    }
}
Kotlin

import org.springframework.boot.ApplicationArguments
import org.springframework.stereotype.Component
@Component
class MyBean(args: ApplicationArguments) {
    init {
        val debug = args.containsOption("debug")
        val files = args.nonOptionArgs
        if (debug) {
            println(files)
        }
        // si se ejecuta con la opción "--debug logfile.txt", prints ["logfile.txt"].
    }
}
Spring Boot también registra CommandLinePropertySource en Environment de Spring. Esto permite, entre otras cosas, inyectar argumentos de aplicación individuales usando la anotación @Value.

Usando ApplicationRunner o CommandLineRunner

Si necesita ejecutar cierto código después de ejecutar SpringApplication, puede implementar las interfaces ApplicationRunner o CommandLineRunner. Ambas interfaces funcionan de la misma manera y proporcionan un único método run que se llama justo antes de que se complete SpringApplication.run(…​).

Este contrato es ideal para tareas que deben realizarse después de que se haya iniciado la aplicación, pero antes de que comience a aceptar tráfico.

La interfaz CommandLineRunner proporciona acceso a los argumentos de la aplicación como una matriz de cadenas, mientras que ApplicationRunner usa la interfaz ApplicationArguments analizada anteriormente. El siguiente ejemplo muestra un CommandLineRunner con un método run:

Java

import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) {
        // hacer algo...
    }
} 
Kotlin

import org.springframework.boot.CommandLineRunner
import org.springframework.stereotype.Component
@Component
class MyCommandLineRunner : CommandLineRunner {
    override fun run(vararg args: String) {
        // hacer algo...
    }
}

Si se definen varios beans CommandLineRunner o ApplicationRunner, deben llamarse en un orden específico, opcionalmente puede implementar la interfaz org.springframework.core.Ordered o usar la anotación org.springframework.core.annotation.Order.

Salir de una aplicación

Cada SpringApplication registra un interceptor de finalización con la JVM para garantizar que ApplicationContext se cierre incrementalmente al salir. Se pueden utilizar todas las devoluciones de llamadas estándar del ciclo de vida de Spring (por ejemplo, la interfaz DisposableBean o la anotación @PreDestroy).

Además, los beans pueden implementar el interfaz org.springframework.boot.ExitCodeGenerator si necesitan devolver un código de salida específico al llamar a SpringApplication.exit(). Este código de salida se puede pasar a System.exit() para devolverlo como código de estado, como se muestra en el siguiente ejemplo:

Java

import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class MyApplication {
    @Bean
    public ExitCodeGenerator exitCodeGenerator() {
        return () -> 42;
    }
    public static void main(String[] args) {
        System.exit(SpringApplication.exit(SpringApplication.run(MyApplication.class, args)));
    }
}
Kotlin

import org.springframework.boot.ExitCodeGenerator
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean
import kotlin.system.exitProcess
@SpringBootApplication
class MyApplication {
    @Bean
    fun exitCodeGenerator() = ExitCodeGenerator { 42 }
}
fun main(args: Array<String>) {
    exitProcess(SpringApplication.exit(
        runApplication<MyApplication>(*args)))
}

Además, se puede implementar la interfaz ExitCodeGenerator con excepciones. Cuando se produce una excepción de este tipo, Spring Boot devuelve el código de salida pasado por el método getExitCode() implementado.

Si hay más de un ExitCodeGenerator, luego, el primer código de salida no nulo generado se utiliza. Para controlar el orden en el que se llaman los generadores, implemente adicionalmente la interfaz org.springframework.core.Ordered o use la anotación org.springframework.core.annotation.Order.< /p>

Funciones de administración

Puede habilitar funciones relacionadas con la administración para una aplicación configurando la propiedad spring.application.admin.enabled. Esto abrirá SpringApplicationAdminMXBean para la plataforma MBeanServer. Puede utilizar esta función para administrar de forma remota su aplicación Spring Boot. Esta función también puede ser útil para cualquier implementación de servicio contenedor.

Si desea saber en qué puerto HTTP se está ejecutando una aplicación, obtenga una propiedad con la clave local.server.port.

Seguimiento de inicio de la aplicación

Durante el inicio de la aplicación SpringApplication y ApplicationContext realizar muchas tareas relacionadas con el ciclo de vida de la aplicación, el ciclo de vida del bean o incluso el manejo de eventos de la aplicación. Con ApplicationStartup, Spring Framework le permite realizar un seguimiento de la secuencia de inicio de una aplicación utilizando objetos StartupStep. Estos datos se pueden recopilar con fines de creación de perfiles o simplemente para comprender mejor el proceso de inicio de la aplicación.

Puede seleccionar la implementación ApplicationStartup al configurar su instancia SpringApplication. . Por ejemplo, para usar BufferingApplicationStartup, podría escribir:

Java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(MyApplication.class);
        application.setApplicationStartup(new BufferingApplicationStartup(2048));
        application.run(args);
    }
}
Kotlin

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup
import org.springframework.boot.runApplication
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
    runApplication<MyApplication>(*args) {
        applicationStartup = BufferingApplicationStartup(2048)
    }
}

La primera implementación disponible, FlightRecorderApplicationStartup, la proporciona Spring Framework. Agrega eventos de inicio relacionados con Spring a la sesión de Java Flight Recorder y está diseñado para perfilar aplicaciones y alinear el ciclo de vida del contexto Spring con eventos JVM (como operaciones de asignación, operaciones de limpieza de memoria, carga de clases...). Una vez configurado, puede registrar datos iniciando la aplicación con Flight Recorder habilitado:

$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar

Spring Boot viene con una variación de BufferingApplicationStartup; esta implementación está diseñada para almacenar en búfer las etapas de inicio y enviarlas a un sistema de métricas externo. Las aplicaciones pueden solicitar un bean de tipo BufferingApplicationStartup en cualquier componente.

Spring Boot también se puede configurar para exponga el punto final startup, que transmite esta información como un documento JSON.