skip to content

How do initMethod and destroyMethod on @Bean work, and how do they compare to other lifecycle callbacks?

level: middleimportance: should knowfreq 45%

answer

  1. init after DI; destroy on context close
  2. order: @PostConstruct → afterPropertiesSet → initMethod
  3. for third-party classes (no annotations needed)
  4. destroyMethod infers close()/shutdown() automatically
  5. destroyMethod="" disables inference; prototypes get no destroy

basics

~10 s

@Bean(initMethod="...") names a method Spring calls after the bean is created and dependencies are set; @Bean(destroyMethod="...") names one called on shutdown. They let you run setup/cleanup on third-party classes without annotations.

solid answer

~40 s

@Bean supports initMethod and destroyMethod attributes naming no-arg methods on the returned object. Spring calls initMethod during initialization — after the constructor and any dependency injection, in the same phase as @PostConstruct and InitializingBean.afterPropertiesSet (order: @PostConstruct, then afterPropertiesSet, then initMethod). destroyMethod runs on singleton bean destruction at context close, alongside @PreDestroy and DisposableBean.destroy. Their value is enabling lifecycle hooks on classes you can't annotate (third-party types), keeping config declarative. A key convenience: for destroyMethod, Spring auto-detects public close() or shutdown() methods by default (inferred destroy method); set destroyMethod="" to disable that inference — useful when the bean is an AutoCloseable you don't want Spring to close, e.g. a shared resource. initMethod/destroyMethod only run for scopes Spring manages fully; prototype beans get init but not destroy callbacks.

code

java · 21 lines
java
@Configuration
class ResourceConfig {

    // Third-party type: hook lifecycle by method name.
    @Bean(initMethod = "start", destroyMethod = "stop")
    EmbeddedBroker broker() {
        return new EmbeddedBroker(9092);
    }

    // HikariDataSource has close(); Spring INFERS it and closes on shutdown.
    @Bean
    DataSource dataSource() {
        return new HikariDataSource();
    }

    // Externally-owned pool: prevent Spring from closing it.
    @Bean(destroyMethod = "")
    ExecutorService sharedPool(ExecutorService external) {
        return external;
    }
}

go deeper

for a junior

Know initMethod runs setup after creation and destroyMethod runs cleanup at shutdown, useful for classes you can't annotate.

for a middle

Explain the ordering vs @PostConstruct/InitializingBean and the inferred close()/shutdown() behavior with destroyMethod="".

for a senior

Discuss prototype-scope destroy limitation, orderly-shutdown requirement, and choosing @PostConstruct vs @Bean callbacks by ownership.

for a principal

Set conventions (annotations for owned code, @Bean attributes for third-party), and reason about resource-leak risks from unexpected inferred close and abrupt shutdowns.

## What they are `@Bean` accepts two attributes for lifecycle callbacks on the *returned object*: - `initMethod = "someInit"` — name of a **no-argument** method Spring invokes after the bean is constructed and fully configured (dependencies injected). - `destroyMethod = "someCleanup"` — name of a **no-argument** method Spring invokes when the bean is destroyed (typically at application context shutdown, for singletons). Because they reference methods **by name**, they work on **third-party classes** you cannot annotate with `@PostConstruct`/`@PreDestroy`. This keeps configuration declarative and centralized. ```java @Bean(initMethod = "start", destroyMethod = "stop") EmbeddedBroker broker() { return new EmbeddedBroker(9092); // third-party, no Spring annotations } ``` ## When they fire (the initialization order) During bean creation Spring runs initialization callbacks in this order: 1. `@PostConstruct`-annotated method 2. `InitializingBean.afterPropertiesSet()` (if the bean implements `InitializingBean`) 3. the `@Bean(initMethod=...)` method All happen **after** constructor and dependency injection, and after `BeanPostProcessor.postProcessBeforeInitialization`. Destruction order (at context close, for singletons): 1. `@PreDestroy`-annotated method 2. `DisposableBean.destroy()` 3. the `@Bean(destroyMethod=...)` method ## Inferred destroy method (a key gotcha) For `destroyMethod`, Spring's default value is a special constant meaning **"infer"**. With inference on, Spring automatically looks for a public **`close()`** or **`shutdown()`** method on the bean and calls it at shutdown — even if you never set `destroyMethod`. This is why a `@Bean` returning a `HikariDataSource` or an `ExecutorService` gets closed automatically. To **disable** this (e.g. the object is `AutoCloseable` but you must NOT close it — a shared/externally-owned resource), set: ```java @Bean(destroyMethod = "") // empty string = no destroy callback, disable inference ExecutorService sharedPool() { return externallyManagedPool; } ``` ## Scope caveats - **Singletons:** both init and destroy callbacks run; destroy fires on context close. - **Prototype beans:** the container creates them and runs **init** callbacks, but does **NOT** track them for destruction — so `destroyMethod`/`@PreDestroy` are **not** called for prototypes. You must clean them up yourself. - Destroy callbacks require an orderly shutdown: `ConfigurableApplicationContext.close()` or a registered shutdown hook. A hard kill (`kill -9`) won't run them. ## initMethod vs @PostConstruct vs InitializingBean — when to use which - **`@PostConstruct` / `@PreDestroy`** (JSR-250): best for **your own** classes; annotation on the method, no config needed. Standard, portable. - **`InitializingBean` / `DisposableBean`**: couples your class to Spring interfaces; generally avoided in favor of annotations. - **`@Bean(initMethod/destroyMethod)`**: best for **third-party** classes or when you want the lifecycle wiring visible in the config rather than the class. ## Common mistakes - Expecting destroy callbacks on prototype beans (they don't run). - Forgetting that inferred `close()`/`shutdown()` will be called automatically — leading to a resource being closed unexpectedly; disable with `destroyMethod=""`. - Giving init/destroy methods parameters (they must be no-arg). - Relying on destroy callbacks after an abrupt JVM kill.

  • You return an AutoCloseable from a @Bean but Spring keeps closing it and you don't want that. Fix?
    Set @Bean(destroyMethod = "") to disable Spring's inferred destroy-method detection, which otherwise auto-invokes close()/shutdown() on shutdown.
  • Do destroyMethod callbacks run for prototype-scoped beans?
    No. Spring doesn't manage the full lifecycle of prototype beans, so it never calls their destroy callbacks (nor @PreDestroy). The caller is responsible for cleanup. Init callbacks do run.

saying these in an interview costs you the question

  • Saying destroyMethod runs for prototype beans — it doesn't.
  • Not knowing Spring auto-infers close()/shutdown() as the destroy method by default.
  • Claiming initMethod runs before dependency injection — it runs after the bean is fully populated.
  • Believing destroy callbacks fire even on kill -9 — only on orderly context close.

context