В дополнение к обычным событиям Spring Framework, таким как ContextRefreshedEvent
, SpringApplication
посылает некоторые дополнительные события приложения.
Некоторые события фактически запускаются до создания ApplicationContext
, поэтому нельзя регистрировать слушателя этих событий в качестве аннотации @Bean
. Вы можете зарегистрировать их с помощью SpringApplication.addListeners(…)
или метода SpringApplicationBuilder.listeners(…)
.
Если нужно, чтобы эти слушатели регистрировались автоматически, независимо от способа создания приложения, то можно добавить файл META-INF/spring.factories
в проект и сослаться на слушатель(и) с помощью ключа org.springframework.context.ApplicationListener
, как показано в следующем примере:
org.springframework.context.ApplicationListener=com.example.project.MyListener
События приложения отправляются в следующем порядке по мере выполнения приложения:
-
Событие
ApplicationStartingEvent
отправляется в начале выполнения, но перед началом любой обработки, за исключением регистрации слушателей и инициализаторов. -
Событие
ApplicationEnvironmentPreparedEvent
отправляется, когдаEnvironment
, которое будет использоваться в контексте, известно, но перед созданием контекста. -
Событие
ApplicationContextInitializedEvent
отправляется, когдаApplicationContext
подготовлен и вызваны ApplicationContextInitializers, но перед загрузкой определений бинов. -
Событие
ApplicationPreparedEvent
отправляется непосредственно перед началом обновления, но после загрузки определений бинов. -
Событие
ApplicationStartedEvent
отправляется после обновления контекста, но перед тем, как будут вызваны все средства выполнения приложения и командной строки. -
Сразу после этого отправляется событие
AvailabilityChangeEvent
сLivenessState.CORRECT
, чтобы обозначить, что приложение считается работающим. -
Событие
ApplicationReadyEvent
отправляется после вызова любого средства выполнения приложений и командной строки. -
Сразу после этого отправляется событие
AvailabilityChangeEvent
сReadinessState.ACCEPTING_TRAFFIC
, чтобы обозначить, что приложение готово к обработке запросов. -
Событие
ApplicationFailedEvent
отправляется, если при запуске возникло исключение.
Приведенный выше список включает только события SpringApplicationEvent
, которые привязаны к SpringApplication
. В дополнение к ним следующие события также публикуются после ApplicationPreparedEvent
и перед ApplicationStartedEvent
:
-
Событие
WebServerInitializedEvent
отправляется после готовностиWebServer
.ServletWebServerInitializedEvent
иReactiveWebServerInitializedEvent
– это варианты сервлета и реактивного сервера соответственно. -
Событие
ContextRefreshedEvent
отправляется, если обновляетсяApplicationContext
.
События приложения отправляются с помощью механизма публикации событий Spring Framework. Часть этого механизма обеспечивает, что событие, опубликованное для слушателей в дочернем контексте, также будет опубликовано для слушателей в любых контекстах-предках. Следовательно, если ваше приложение использует иерархию экземпляров SpringApplication
, слушатель может получить несколько экземпляров одного и того же типа события приложения.
Чтобы слушатель мог отличить событие для своего контекста от события для дочернего контекста, он должен запросить внедрение своего контекста приложения, а затем сравнить внедренный контекст с контекстом события. Контекст может быть внедрен путем реализации ApplicationContextAware
или, если слушатель является бином, с помощью аннотации @Autowired
.
Веб-окружение
SpringApplication
пытается создать нужный тип ApplicationContext
по вашему указанию. Для определения WebApplicationType
используется следующий алгоритм:
-
Если присутствует Spring MVC, используется
AnnotationConfigServletWebServerApplicationContext
-
Если Spring MVC отсутствует, а Spring WebFlux присутствует, используется
AnnotationConfigReactiveWebServerApplicationContext
-
В противном случае используется
AnnotationConfigApplicationContext
Это означает, что если вы используете Spring MVC и новый WebClient
из Spring WebFlux в одном приложении, Spring MVC будет использоваться по умолчанию. Вы можете легко переопределить это, вызвав setWebApplicationType(WebApplicationType)
.
Также можно полностью управлять используемым типом ApplicationContext
, вызывая setApplicationContextClass(…)
.
setWebApplicationType(WebApplicationType.NONE)
при использовании SpringApplication
в тесте JUnit.Доступ к аргументам приложения
Если необходимо получить доступ к аргументам приложения, которые были переданы в SpringApplication.run(…)
, можно внедрить бин org.springframework.boot.ApplicationArguments
. Интерфейс ApplicationArguments
предоставляет доступ как к сырым аргументам String[]
, так и к парсированным аргументам option
и non-option
, как показано в следующем примере:
@Component
public class MyBean {
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
if (debug) {
System.out.println(files);
}
// если запустить с параметром "--debug logfile.txt", выводится ["logfile.txt"].
}
}
@Component
class MyBean(args: ApplicationArguments) {
init {
val debug = args.containsOption("debug")
val files = args.nonOptionArgs
if (debug) {
println(files)
}
// если запустить с параметром "--debug logfile.txt", выводится ["logfile.txt"].
}
}
CommandLinePropertySource
в Environment
из Spring. Это позволяет помимо прочего внедрять отдельные аргументы приложения с помощью аннотации @Value
.Использование ApplicationRunner или CommandLineRunner
Если необходимо выполнить определенный код после запуска SpringApplication
, можно реализовать интерфейсы ApplicationRunner
или CommandLineRunner
. Оба интерфейса работают одинаково и предусматривают один метод run
, который вызывается непосредственно перед тем, как SpringApplication.run(…)
будет завершен.
Интерфейс CommandLineRunner
предоставляет доступ к аргументам приложения в виде массива строк, в то время как ApplicationRunner
использует интерфейс ApplicationArguments
, рассмотренный ранее. В следующем примере показан CommandLineRunner
с методом run
:
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// делаем что-то...
}
}
@Component
class MyCommandLineRunner : CommandLineRunner {
override fun run(vararg args: String) {
// делаем что-то...
}
}
Если определено несколько бинов CommandLineRunner
или ApplicationRunner
, которые должны вызываться в определенном порядке, можно дополнительно реализовать интерфейс org.springframework.core.Ordered
или использовать аннотацию org.springframework.core.annotation.Order
.
Выход из приложения
Каждое SpringApplication
регистрирует перехватчик завершения в JVM, чтобы обеспечить поэтапное закрытие ApplicationContext
при выходе. Можно использовать все стандартные обратные вызовы жизненного цикла Spring (например, интерфейс DisposableBean
или аннотацию @PreDestroy
).
Кроме того, бины могут реализовать интерфейс org.springframework.boot.ExitCodeGenerator
, если им нужно возвращать определенный код выхода при вызове SpringApplication.exit()
. Этот код выхода можно передать в System.exit()
, чтобы вернуть его в качестве кода состояния, как показано в следующем примере:
@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)));
}
}
@SpringBootApplication
class MyApplication {
@Bean
fun exitCodeGenerator() = ExitCodeGenerator { 42 }
}
fun main(args: Array<String>) {
exitProcess(SpringApplication.exit(
runApplication<MyApplication>(*args)))
}
Кроме того, интерфейс ExitCodeGenerator
может быть реализован исключениями. При возникновении такого исключения Spring Boot возвращает код выхода, передаваемый реализованным методом getExitCode()
.
Если существует более чем один ExitCodeGenerator
, то используется первый сгенерированный ненулевой код выхода. Чтобы управлять порядком вызова генераторов, дополнительно реализуйте интерфейс org.springframework.core.Ordered
или используйте аннотацию org.springframework.core.annotation.Order
.
Функции администрирования
Можно включить функции, связанные с администрированием, для приложения, задав свойство spring.application.admin.enabled
. Это откроет SpringApplicationAdminMXBean
для платформы MBeanServer
. Можно использовать эту функцию для удаленного администрирования приложения Spring Boot. Эта функция также может быть полезна для любой реализации службы-обёртки.
local.server.port
.Отслеживание запуска приложений
Во время запуска приложения SpringApplication
и ApplicationContext
выполняют множество задач, связанных с жизненным циклом приложения, жизненным циклом бинов или даже с обработкой событий приложения. Благодаря ApplicationStartup
Spring Framework позволяет отслеживать последовательность запуска приложения с помощью объектов StartupStep
. Эти данные можно собирать в целях профилирования или просто для лучшего понимания процесса запуска приложения.
Имеется возможность выбора реализации ApplicationStartup
при настройке экземпляра SpringApplication
. Например, чтобы использовать 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);
}
}
@SpringBootApplication
class MyApplication
fun main(args: Array<String>) {
runApplication<MyApplication>(*args) {
applicationStartup = BufferingApplicationStartup(2048)
}
}
Первая доступная реализация, FlightRecorderApplicationStartup
, предусматривается Spring Framework. Она добавляет связанные со Spring события запуска в сессию Java Flight Recorder и предназначена для профилирования приложений и приведение жизненного цикла Spring-контекста в соответствие с событиями JVM (такими как операции выделения, операции очистки памяти от ненужных данных, загрузка классов...). После конфигурирования можно записывать данные, запустив приложение с активированным Flight Recorder:
$ java -XX:StartFlightRecording:filename=recording.jfr,duration=10s -jar demo.jar
Spring Boot поставляется с вариацией BufferingApplicationStartup
; эта реализация предназначена для буферизации этапов запуска и сброса их во внешнюю систему метрик. Приложения могут запрашивать бин типа BufferingApplicationStartup
в любом компоненте.
Spring Boot также можно сконфигурировать так, чтобы он открывал конечную точку startup
, которая передает эту информацию в виде документа JSON.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ