How do initMethod and destroyMethod on @Bean work, and how do they compare to other lifecycle callbacks?
answer
- init after DI; destroy on context close
- order: @PostConstruct → afterPropertiesSet → initMethod
- for third-party classes (no annotations needed)
- destroyMethod infers close()/shutdown() automatically
- 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@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
Know initMethod runs setup after creation and destroyMethod runs cleanup at shutdown, useful for classes you can't annotate.
Explain the ordering vs @PostConstruct/InitializingBean and the inferred close()/shutdown() behavior with destroyMethod="".
Discuss prototype-scope destroy limitation, orderly-shutdown requirement, and choosing @PostConstruct vs @Bean callbacks by ownership.
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.