В дополнение к обычным событиям 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.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ