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:
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.El evento
ApplicationEnvironmentPreparedEvent
se envía cuando se conoce elEnvironment
que se utilizará en el contexto, pero antes de que se cree el contexto.El
ApplicationContextInitializedEvent
se distribuye cuando se prepara elApplicationContext
y se llama a ApplicationContextInitializers, pero antes de que se carguen las definiciones de bean.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.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.Inmediatamente después de esto, se envía un el evento
AvailabilityChangeEvent
se envía conLivenessState.CORRECT
para indicar que se considera que la aplicación se está ejecutando.El evento
ApplicationReadyEvent
se envía después de invocar cualquier aplicación y ejecutor de línea de comando.Inmediatamente después,
AvailabilityChangeEvent
se envía conReadinessState.ACCEPTING_TRAFFIC
para indicar que la aplicación está lista para procesar solicitudes.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 cuandoWebServer
está listo.ServletWebServerInitializedEvent
yReactiveWebServerInitializedEvent
son variantes de servlet y servidor reactivo respectivamente.El evento
ContextRefreshedEvent
se envía, siApplicationContext
está actualizado.
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(…)
.
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:
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.
}
}
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"].
}
}
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(…)
.
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
:
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// hacer algo...
}
}
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:
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)));
}
}
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.
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:
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);
}
}
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.