skip to content

If a bean uses @PostConstruct, implements InitializingBean, and also declares an @Bean initMethod, in what order do the init callbacks run?

level: middleimportance: must knowfreq 65%

answer

  1. Init: annotation → interface → declared method
  2. @PostConstruct → afterPropertiesSet → initMethod
  3. Destroy mirrors: @PreDestroy → destroy() → destroyMethod
  4. Same method twice = called once
  5. @PostConstruct fires in postProcessBeforeInitialization

basics

~10 s

First @PostConstruct, then InitializingBean.afterPropertiesSet(), then the @Bean initMethod. Destruction mirrors it: @PreDestroy, then DisposableBean.destroy(), then the @Bean destroyMethod.

solid answer

~30 s

Spring runs all three init hooks in a fixed order. First the JSR-250 @PostConstruct method (invoked by CommonAnnotationBeanPostProcessor, a BeanPostProcessor that runs during postProcessBeforeInitialization). Then InitializingBean.afterPropertiesSet(). Then the custom init method named via @Bean(initMethod) or XML init-method. Destruction is the mirror image: @PreDestroy first, then DisposableBean.destroy(), then the configured destroyMethod. The mnemonic is annotation → interface → declared-method for both directions. A subtle detail: if the same physical method is referenced by more than one mechanism (say it's both @PostConstruct-annotated and named as initMethod), Spring recognizes the duplicate and invokes it only once rather than twice.

code

java · 16 lines
java
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.InitializingBean;

class Ordered implements InitializingBean {
    @PostConstruct
    void a() { System.out.println("1: @PostConstruct"); }

    @Override
    public void afterPropertiesSet() { System.out.println("2: afterPropertiesSet"); }

    void c() { System.out.println("3: initMethod"); }
}

// @Bean(initMethod = "c")
// Ordered ordered() { return new Ordered(); }
// Prints 1, then 2, then 3.

go deeper

for a junior

Just remember the sequence: @PostConstruct, then afterPropertiesSet, then initMethod.

for a middle

State the order confidently for both init and destroy and know the de-dup rule.

for a senior

Tie the order to the post-processor vs invokeInitMethods split and the surrounding creation flow.

for a principal

Discuss where AOP proxying sits, intra- vs inter-bean ordering, and why layering exists.

When a single bean wires up **all three** initialization mechanisms, Spring executes them in a **deterministic, documented order**. Understanding *why* requires knowing that `@PostConstruct`/`@PreDestroy` are handled by a `BeanPostProcessor` (the `CommonAnnotationBeanPostProcessor`, technically its superclass `InitDestroyAnnotationBeanPostProcessor`), while the interface and declared-method callbacks are handled by the core bean factory's `invokeInitMethods`. **Initialization order:** 1. **`@PostConstruct`** — runs inside `postProcessBeforeInitialization`, i.e. *before* the factory's own init-method invocation. 2. **`InitializingBean.afterPropertiesSet()`** — the factory calls this first inside `invokeInitMethods`. 3. **Custom init method** — `@Bean(initMethod = "...")` (or XML `init-method`), invoked by reflection immediately after `afterPropertiesSet()`. **Destruction order (the mirror):** 1. **`@PreDestroy`** — via the same post-processor's destroy path. 2. **`DisposableBean.destroy()`**. 3. **Custom destroy method** — `@Bean(destroyMethod = "...")` / XML `destroy-method`. So the rule for both directions is: **annotation → interface → declared method**. **Where this order sits in the overall bean creation flow:** constructor → dependency injection (setters/fields) → `BeanNameAware`/`BeanFactoryAware`/`ApplicationContextAware` etc. `set*` methods → `BeanPostProcessor.postProcessBeforeInitialization` (this is where `@PostConstruct` fires) → `afterPropertiesSet()` → custom init method → `BeanPostProcessor.postProcessAfterInitialization` (where AOP proxies are typically created) → bean ready. On shutdown the destroy order above runs in reverse relative to init. **De-duplication gotcha:** If you point two mechanisms at the *same* method — e.g. a method named `init()` that is both `@PostConstruct`-annotated and declared as `@Bean(initMethod = "init")` — Spring detects the collision and calls it **only once**, not twice. This prevents accidental double-initialization when developers combine styles. **Cross-bean ordering is different:** This ordering is *within one bean*. Across beans, init callbacks respect the dependency graph — a bean's dependencies are fully initialized (including their `@PostConstruct`) before the dependent bean's init callbacks run. You can nudge inter-bean ordering with `@DependsOn`, but you cannot reorder the three intra-bean hooks. **Why it matters:** Rarely do you use all three, but interviewers use this to check whether you understand that these mechanisms are *layered*, not mutually exclusive, and that the container has a single well-defined sequence. In practice, pick one mechanism per concern to keep the sequence obvious.

  • What happens if the same method is both @PostConstruct-annotated and named as the @Bean initMethod?
    Spring recognizes it's the same method and invokes it only once, avoiding a double call.
  • At what stage of bean creation does @PostConstruct actually fire relative to AOP proxy creation?
    @PostConstruct runs during postProcessBeforeInitialization; AOP proxies are usually created in postProcessAfterInitialization, so @PostConstruct executes on the raw target before proxying.

saying these in an interview costs you the question

  • Saying afterPropertiesSet() runs before @PostConstruct
  • Claiming the order is undefined or depends on registration order
  • Believing the same method gets called twice when wired by two mechanisms

context