Walk through the ordered sequence of Spring Boot application lifecycle events during startup.
answer
- Starting → EnvPrepared → ContextInitialized → Prepared → (refresh) → Started → Ready
- Failed replaces the rest
- first three = no beans yet
- Prepared = bean defs loaded, pre-refresh
- Started before runners, Ready after runners
basics
~10 sRoughly: ApplicationStartingEvent, then ApplicationEnvironmentPreparedEvent, then ApplicationContextInitializedEvent, then ApplicationPreparedEvent (context refreshes here), then ApplicationStartedEvent, then ApplicationReadyEvent. On error, ApplicationFailedEvent fires instead.
solid answer
~40 sSpringApplication.run drives an ordered event sequence via SpringApplicationRunListener callbacks. (1) ApplicationStartingEvent — earliest, before Environment or context, only listeners/initializers registered. (2) ApplicationEnvironmentPreparedEvent — Environment is built (properties, profiles) but no context yet; this is where config data is bound and where things like EnvironmentPostProcessors act. (3) ApplicationContextInitializedEvent — context created, ApplicationContextInitializers applied, bean definitions not loaded. (4) ApplicationPreparedEvent — bean definitions loaded, just before refresh. Then the context refreshes (ContextRefreshedEvent). (5) ApplicationStartedEvent — after refresh, before runners; plus an AvailabilityChangeEvent to LivenessState.CORRECT. (6) ApplicationReadyEvent — after all runners, plus AvailabilityChangeEvent to ACCEPTING_TRAFFIC. Any exception publishes ApplicationFailedEvent. Events before ApplicationPreparedEvent cannot be caught by @EventListener beans — the context doesn't exist yet.
code
java · 8 lines// Registering a listener that must catch the EARLY events (before context exists)
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MyApp.class);
app.addListeners((ApplicationListener<ApplicationStartingEvent>) e ->
System.out.println("very early: no Environment/context yet"));
app.run(args);
}
// A @Component @EventListener bean could only catch ApplicationPreparedEvent onward.go deeper
Recall the coarse order and that Failed replaces the rest on error.
Reproduce the full ordered list and know which events precede bean existence.
Explain the SpringApplicationRunListener callback backing each event and where EnvironmentPostProcessor/ContextInitializer hook in.
Discuss availability-state events, refresh vs Boot events, and designing early hooks that can't rely on the container.
## The mental model `SpringApplication.run()` is not one atomic step; it is a pipeline. Spring Boot exposes that pipeline through **`SpringApplicationRunListener`** callbacks, and for each phase it publishes a corresponding **application event**. Knowing the order tells you *what state exists* when your code runs. ## The ordered sequence (happy path) 1. **ApplicationStartingEvent** — published as soon as the run starts, right after listeners and `ApplicationContextInitializer`s are registered. **No Environment, no context, no beans.** Useful only for very early diagnostics/logging registration. 2. **ApplicationEnvironmentPreparedEvent** — the `Environment` (property sources, active profiles, `application.yml`/`application.properties`) is prepared, but the `ApplicationContext` still does **not** exist. This is the phase where config data is available and where `EnvironmentPostProcessor` implementations mutate configuration. 3. **ApplicationContextInitializedEvent** — the `ApplicationContext` object has been **created** and all `ApplicationContextInitializer`s have run, but **bean definitions are not yet loaded**. 4. **ApplicationPreparedEvent** — bean **definitions are loaded** into the context, immediately **before refresh**. This is the first event that a bean-based `@EventListener` can realistically catch, because listener beans registered in the context are now known (though not all singletons are instantiated). 5. *(context refresh happens — the standard `ContextRefreshedEvent` is published by the container itself)*. 6. **ApplicationStartedEvent** — published after refresh completes but **before** any `ApplicationRunner`/`CommandLineRunner`. Boot also fires `AvailabilityChangeEvent` → `LivenessState.CORRECT`. 7. **ApplicationReadyEvent** — published after **all** runners finish; the app is fully live. Boot also fires `AvailabilityChangeEvent` → `ReadinessState.ACCEPTING_TRAFFIC`. ## Failure path If **any** step throws, Boot publishes **ApplicationFailedEvent** (with the exception) instead of continuing. Listeners on this event can log, alert, or clean up before the process exits. ## Why the ordering matters - The first three events (Starting, EnvironmentPrepared, ContextInitialized) occur **before beans exist**, so you cannot use `@Component` + `@EventListener` to observe them. You must register an `ApplicationListener` **before** the context is built — via `SpringApplication.addListeners(...)`, `SpringApplicationBuilder.listeners(...)`, or `META-INF/spring.factories`. - ApplicationPreparedEvent onward is safe for context-based listeners. ## Common gotchas - Confusing `ContextRefreshedEvent` (a core `ApplicationContext` event, can fire on any refresh, e.g. actuator restart) with `ApplicationReadyEvent` (a Boot-specific, once-per-successful-run event). - Expecting property values in an ApplicationStartingEvent listener — the Environment isn't ready yet. - Assuming ApplicationFailedEvent means the context was built — it may fire before the context even exists. ## When to use which - Diagnostics from the very start → ApplicationStartingEvent. - Adjust/inspect configuration → ApplicationEnvironmentPreparedEvent (or EnvironmentPostProcessor). - Post-config, pre-refresh customization of the context → ApplicationContextInitializedEvent. - 'App fully live' side effects → ApplicationReadyEvent. - Boot-failure alerting → ApplicationFailedEvent.
- At which point in the sequence does the ApplicationContext first exist?At ApplicationContextInitializedEvent — the context object is created and initializers have run, though bean definitions aren't loaded until ApplicationPreparedEvent.
- Which is the earliest event a normal @Component @EventListener can reliably observe?ApplicationPreparedEvent, because bean definitions are loaded and listener beans in the context are registered; earlier events fire before beans exist.
saying these in an interview costs you the question
- Putting ApplicationReadyEvent before ApplicationStartedEvent
- Claiming the Environment is available at ApplicationStartingEvent
- Saying @EventListener beans can catch ApplicationStartingEvent
- Treating ContextRefreshedEvent and ApplicationReadyEvent as the same event