skip to content

What is an ApplicationContextInitializer and when does it run?

level: middleimportance: should knowfreq 30%

answer

  1. initialize(ctx) — runs before refresh()
  2. customize Environment / add property sources / profiles
  3. register via addInitializers / spring.factories / context.initializer.classes
  4. ordered by @Order
  5. NOT ApplicationRunner (that's post-refresh)

basics

~10 s

ApplicationContextInitializer is a callback you implement to configure the ConfigurableApplicationContext before refresh() is called. It's commonly used in Spring Boot to add property sources, activate profiles, or register beans very early in startup.

solid answer

~30 s

ApplicationContextInitializer<C extends ConfigurableApplicationContext> is a single-method callback, initialize(C ctx), invoked after the context is created but before refresh() runs — so before any bean definitions are processed or singletons built. That early window lets you programmatically customize the environment (add PropertySources, set active profiles), register additional bean definitions, or add BeanFactoryPostProcessors. In Spring Boot you register initializers via SpringApplication.addInitializers(...), the context.initializer.classes property, or META-INF/spring.factories (spring.factories) / spring/org.springframework.context.ApplicationContextInitializer.imports. They run in Order/@Order sequence. Outside Boot you'd call the initializer manually before invoking refresh() yourself.

code

java · 16 lines
java
public class ProfilePropsInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {
    @Override
    public void initialize(ConfigurableApplicationContext ctx) {
        // runs BEFORE refresh() — safe to shape the environment
        var env = ctx.getEnvironment();
        env.addActiveProfile("cloud");
        env.getPropertySources().addFirst(
            new MapPropertySource("early", Map.of("feature.x.enabled", "true")));
    }
}

// Boot registration:
new SpringApplicationBuilder(App.class)
        .initializers(new ProfilePropsInitializer())
        .run(args);

go deeper

for a junior

Know it's an early startup callback used to tweak the context before beans are created.

for a middle

Explain the pre-refresh timing, typical uses (property sources/profiles), and the Boot registration mechanisms.

for a senior

Detail ordering, adding BeanFactoryPostProcessors, and contrast with post-refresh runners; explain manual invocation outside Boot.

for a principal

Discuss where initializers fit in a bootstrap strategy (cloud env detection, config precedence) and their auto-discovery via spring.factories in a modular/library context.

**Definition.** `ApplicationContextInitializer<C extends ConfigurableApplicationContext>` is a functional interface with one method, `void initialize(C applicationContext)`. It is a *pre-refresh* hook: the framework hands you the freshly created but not-yet-refreshed context so you can mutate it before the startup pipeline runs. **Timing.** The initializer runs **after the `ApplicationContext` object exists but before `refresh()`** (before `prepareRefresh` / bean-definition processing / singleton creation). At this point the bean factory has no user singletons yet, so anything you do influences the entire startup. **What you can do inside it:** - **Customize the `Environment`** — e.g. `ctx.getEnvironment().getPropertySources().addFirst(new MapPropertySource(...))` to inject high-priority properties, or `getEnvironment().addActiveProfile("x")`. - **Register bean definitions** — cast/register into the `GenericApplicationContext` or add an `ApplicationContextInitializer`-driven configuration. - **Add a `BeanFactoryPostProcessor`** via `ctx.addBeanFactoryPostProcessor(...)` to run during refresh (BFPP mechanics are a sibling topic; here it's just where you *attach* one early). - **Set the context id, register shutdown behavior, etc.** **How they're registered in Spring Boot:** 1. Programmatically: `new SpringApplicationBuilder(App.class).initializers(new MyInitializer()).run(args)` or `springApplication.addInitializers(...)`. 2. Property: `context.initializer.classes=com.acme.MyInitializer` (in `application.properties` or as a system property). 3. Auto-discovery: listed under `org.springframework.context.ApplicationContextInitializer` in `META-INF/spring.factories` (classic) or `META-INF/spring/org.springframework.context.ApplicationContextInitializer.imports` (newer). Boot itself uses these for internal initializers. **Ordering.** Multiple initializers are sorted by `Ordered`/`@Order`/`PriorityOrdered` before being invoked in turn. **Outside Spring Boot** (plain `GenericApplicationContext`): there is no automatic invocation — you call `new MyInitializer().initialize(ctx)` yourself *before* `ctx.refresh()`. **Typical use cases:** inject environment-specific or externally-computed properties before any `@Value`/`@ConfigurationProperties` binding; enable a profile based on runtime detection (cloud platform, feature flag); register infrastructure beans that must exist before user config; set up early logging/metrics context. **Gotchas:** (a) It's *not* the same as an `ApplicationRunner`/`CommandLineRunner` (those run *after* refresh, when the app is ready). (b) Because it runs before refresh, you can't `getBean(...)` a user bean inside it — nothing is instantiated yet. (c) The generic type must match the context type or you'll get a registration/casting failure.

  • How is an ApplicationContextInitializer different from a CommandLineRunner/ApplicationRunner?
    The initializer runs before refresh() (no beans exist yet) and shapes the context/environment; CommandLineRunner/ApplicationRunner run after refresh() when the context is fully started and all beans are available.
  • Can you call getBean() inside an ApplicationContextInitializer?
    No — it executes before refresh(), so singletons haven't been instantiated. You can register definitions or add property sources, but you can't retrieve user beans yet.

saying these in an interview costs you the question

  • Saying it runs after the context is fully started (it runs before refresh)
  • Confusing it with ApplicationRunner/CommandLineRunner
  • Trying to getBean() user beans inside initialize()
  • Thinking it only works in Spring Boot (the interface is core Spring; Boot just automates registration)

context