应用启动时到底按什么顺序触发了哪些事件?@Component 里写的监听器为什么收不到 ApplicationStartingEvent?runner 在 Ready 之前还是之后跑?慢的 runner 会不会让端口一直关着?这篇在 Spring Boot 4.0.8 上把每个阶段都打了点。
+ 0 ms [main] main() 开始 + 201 ms [A] ApplicationStartingEvent + 201 ms [R] starting + 319 ms [A] ApplicationEnvironmentPreparedEvent (此时 app.v=from-file) + 319 ms [R] environmentPrepared (此时 app.v=from-file) + 351 ms [A] ApplicationContextInitializedEvent (Bean 定义 5 个, isActive=false) + 351 ms [R] contextPrepared (Bean 定义 5 个, isActive=false) + 374 ms [A] ApplicationPreparedEvent (Bean 定义 6 个, isActive=false) + 374 ms [R] contextLoaded (Bean 定义 6 个, isActive=false) + 523 ms [bean] 某个 Bean 的 @PostConstruct + 544 ms [life] SmartLifecycle.start() + 545 ms [A] ContextRefreshedEvent (Bean 定义 56 个, isActive=true) + 545 ms [A] ApplicationStartedEvent (Bean 定义 56 个, isActive=true) + 546 ms [A] AvailabilityChangeEvent (LivenessState.CORRECT) + 546 ms [R] started + 547 ms [run] R1 CommandLineRunner @Order(1) (args=[--foo=bar, --flag, baz]) + 551 ms [run] R2 ApplicationRunner @Order(2) (options=[flag, foo] nonOption=[baz] foo=[bar] flag=[]) + 551 ms [run] R3 CommandLineRunner(没有 @Order) + 552 ms [A] ApplicationReadyEvent (Bean 定义 56 个, isActive=true) + 552 ms [A] AvailabilityChangeEvent (ReadinessState.ACCEPTING_TRAFFIC) + 552 ms [R] ready + 552 ms [main] app.run() 返回 + 553 ms [A] ContextClosedEvent 退出码 0
Starting → EnvironmentPrepared → ContextInitialized → Prepared → refresh → ContextRefreshed → Started → runners → Ready;配置文件在 EnvironmentPrepared 之前加载好。
[A] app.addListeners(...):共 10 个——ApplicationStarting、ApplicationEnvironmentPrepared、ApplicationContextInitialized、ApplicationPrepared、ContextRefreshed、ApplicationStarted、AvailabilityChange、ApplicationReady、AvailabilityChange、ContextClosed [B] @Component:共 6 个——ContextRefreshed、ApplicationStarted、AvailabilityChange、ApplicationReady、AvailabilityChange、ContextClosed [C] spring.factories 的 ApplicationListener:共 10 个——ApplicationStarting、ApplicationEnvironmentPrepared、ApplicationContextInitialized、ApplicationPrepared、ContextRefreshed、ApplicationStarted、AvailabilityChange、ApplicationReady、AvailabilityChange、ContextClosed [R] spring.factories 的 SpringApplicationRunListener:共 6 个——starting、environmentPrepared、contextPrepared、contextLoaded、started、ready
addListeners 与 spring.factories 能收到全部;@Component 的监听器只收到 refresh 之后的 6 个。
-- Bean 的 @PostConstruct 抛异常: + 0 ms [main] main() 开始 + 171 ms [A] ApplicationStartingEvent + 171 ms [R] starting + 261 ms [A] ApplicationEnvironmentPreparedEvent (此时 app.v=null) + 261 ms [R] environmentPrepared (此时 app.v=null) + 292 ms [A] ApplicationContextInitializedEvent (Bean 定义 5 个, isActive=false) + 292 ms [R] contextPrepared (Bean 定义 5 个, isActive=false) + 313 ms [A] ApplicationPreparedEvent (Bean 定义 6 个, isActive=false) + 313 ms [R] contextLoaded (Bean 定义 6 个, isActive=false) + 454 ms [bean] 某个 Bean 的 @PostConstruct + 457 ms [A] ApplicationFailedEvent (BeanCreationException: Error creating bean with name 'bad': Invocation of init method failed) + 457 ms [R] failed (BeanCreationException) 退出码 1;堆栈里的异常:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bad': Invocation of init method failed -- 最后一个 runner 抛异常: + 0 ms [main] main() 开始 + 186 ms [A] ApplicationStartingEvent + 186 ms [R] starting + 276 ms [A] ApplicationEnvironmentPreparedEvent (此时 app.v=null) + 276 ms [R] environmentPrepared (此时 app.v=null) + 308 ms [A] ApplicationContextInitializedEvent (Bean 定义 5 个, isActive=false) + 308 ms [R] contextPrepared (Bean 定义 5 个, isActive=false) + 331 ms [A] ApplicationPreparedEvent (Bean 定义 6 个, isActive=false) + 332 ms [R] contextLoaded (Bean 定义 6 个, isActive=false) + 471 ms [bean] 某个 Bean 的 @PostConstruct + 494 ms [A] ContextRefreshedEvent (Bean 定义 56 个, isActive=true) + 494 ms [A] ApplicationStartedEvent (Bean 定义 56 个, isActive=true) + 495 ms [A] AvailabilityChangeEvent (LivenessState.CORRECT) + 495 ms [R] started + 496 ms [run] R1 CommandLineRunner @Order(1) (args=[]) + 496 ms [run] R2 ApplicationRunner @Order(2) (options=[] nonOption=[] foo=null flag=null) + 496 ms [run] R3 CommandLineRunner(没有 @Order) + 497 ms [A] ApplicationFailedEvent (IllegalStateException: boom in runner) + 497 ms [R] failed (IllegalStateException) + 504 ms [A] ContextClosedEvent 退出码 1;堆栈里的异常:java.lang.IllegalStateException: boom in runner -- 用 SpringApplication.exit(ctx, () -> 42) 主动退出: + 0 ms [main] main() 开始 + 177 ms [A] ApplicationStartingEvent + 266 ms [A] ApplicationEnvironmentPreparedEvent (此时 app.v=null) + 303 ms [A] ApplicationContextInitializedEvent (Bean 定义 5 个, isActive=false) + 331 ms [A] ApplicationPreparedEvent (Bean 定义 6 个, isActive=false) + 534 ms [A] ContextRefreshedEvent (Bean 定义 56 个, isActive=true) + 534 ms [A] ApplicationStartedEvent (Bean 定义 56 个, isActive=true) + 535 ms [A] AvailabilityChangeEvent (LivenessState.CORRECT) + 537 ms [A] ApplicationReadyEvent (Bean 定义 56 个, isActive=true) + 537 ms [A] AvailabilityChangeEvent (ReadinessState.ACCEPTING_TRAFFIC) + 537 ms [main] app.run() 返回 + 538 ms [A] ExitCodeEvent (exitCode=42) + 538 ms [A] ContextClosedEvent + 539 ms [main] SpringApplication.exit 返回 (code=42) 退出码 42
Bean 初始化失败与 runner 抛异常都是退出码 1,前者没有 ContextClosed,后者没有 Ready;SpringApplication.exit 可以自定义退出码。
+ 190 ms [A] ApplicationStartingEvent + 289 ms [A] ApplicationEnvironmentPreparedEvent (此时 app.v=null) + 327 ms [A] ApplicationContextInitializedEvent (Bean 定义 5 个, isActive=false) + 350 ms [A] ApplicationPreparedEvent (Bean 定义 6 个, isActive=false) + 758 ms [bean] 某个 Bean 的 @PostConstruct + 870 ms 【外部客户端】第一次连上端口 + 878 ms [A] ServletWebServerInitializedEvent + 878 ms [life] SmartLifecycle.start() + 879 ms [A] ContextRefreshedEvent (Bean 定义 150 个, isActive=true) + 880 ms [A] ApplicationStartedEvent (Bean 定义 150 个, isActive=true) + 881 ms [A] AvailabilityChangeEvent (LivenessState.CORRECT) + 882 ms [run] R1 CommandLineRunner @Order(1) (args=[]) + 882 ms [run] R2 ApplicationRunner @Order(2) (options=[] nonOption=[] foo=null flag=null) + 882 ms [run] R3 CommandLineRunner(没有 @Order) + 914 ms 【外部客户端】GET /state 收到响应:HTTP 200 liveness=CORRECT readiness=REFUSING_TRAFFIC +2388 ms [run] R3 慢 runner 结束 (睡了 1500 ms) +2389 ms [A] ApplicationReadyEvent (Bean 定义 150 个, isActive=true) +2389 ms [A] AvailabilityChangeEvent (ReadinessState.ACCEPTING_TRAFFIC) runner 结束之后再请求一次:HTTP 200 liveness=CORRECT readiness=ACCEPTING_TRAFFIC
内嵌容器的端口在 runner 之前就开放;runner 期间 readiness 是 REFUSING_TRAFFIC,Ready 事件之后才变 ACCEPTING_TRAFFIC。