skip to content

Walk through the ordered sequence of Spring Boot application lifecycle events during startup.

level: middleimportance: should knowfreq 45%

answer

  1. Starting → EnvPrepared → ContextInitialized → Prepared → (refresh) → Started → Ready
  2. Failed replaces the rest
  3. first three = no beans yet
  4. Prepared = bean defs loaded, pre-refresh
  5. Started before runners, Ready after runners

basics

~10 s

Roughly: ApplicationStartingEvent, then ApplicationEnvironmentPreparedEvent, then ApplicationContextInitializedEvent, then ApplicationPreparedEvent (context refreshes here), then ApplicationStartedEvent, then ApplicationReadyEvent. On error, ApplicationFailedEvent fires instead.

solid answer

~40 s

SpringApplication.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
java
// 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

for a junior

Recall the coarse order and that Failed replaces the rest on error.

for a middle

Reproduce the full ordered list and know which events precede bean existence.

for a senior

Explain the SpringApplicationRunListener callback backing each event and where EnvironmentPostProcessor/ContextInitializer hook in.

for a principal

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

context