На додаток до звичайних подій 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
, як показано в наступному прикладі:
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);
}
// якщо запустити з параметром "--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)
}
// якщо запустити з параметром "--debug logfile.txt", prints ["logfile.txt"].
}
}
CommandLinePropertySource
в Environment
зі Spring. Це дозволяє також впроваджувати окремі аргументи програми за допомогою анотації @Value
.
Використання ApplicationRunner або CommandLineRunner
Якщо необхідно виконати певний код після запуску
SpringApplication
можна реалізувати інтерфейси ApplicationRunner
або CommandLineRunner
.
Обидва інтерфейси працюють однаково і передбачають один метод run
, який викликається безпосередньо
перед тим, як SpringApplication.run(…)
буде завершено.
Інтерфейс CommandLineRunner
надає доступ до аргументів програми у вигляді масиву рядків, тоді як
ApplicationRunner
використовує інтерфейс ApplicationArguments
, розглянутий раніше. У
наступному прикладі показано CommandLineRunner
з методом run
:
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) {
// робимо щось...
}
}
import org.springframework.boot.CommandLineRunner
import org.springframework.stereotype.Component
@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()
, щоб повернути його як код стану, як показано в наступному прикладі:
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)))
}
До того ж, інтерфейс 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
, можна написати:
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)
}
}
Перша доступна реалізація, 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.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ