@PostConstruct and @PreDestroy — Bean Initialization and Destruction Callbacks
Fast recall
Quick revision
Core answer
@Autowired collaborators (the constructor can't, for field injection). `@PreDestroy` marks a method called when the container shuts down — close resources, flush caches, stop schedulers. Callback order on a single bean: @PostConstruct → InitializingBean.afterPropertiesSet() → custom @Bean(initMethod="..."). Destruction mirrors in reverse, in reverse bean-creation order. Critical gotcha: @PreDestroy never fires on prototype beans — Spring creates them but doesn't track them after creation. In Jakarta EE migration (Spring Boot 3+), imports moved from javax.annotation to jakarta.annotation.Whether you know why constructors aren't safe for field-injected dependencies, the callback ordering when multiple mechanisms coexist, and the prototype destruction gotcha
Using @PostConstruct to initialize state that could go in the constructor; assuming @PreDestroy runs on prototype beans; forgetting the Jakarta migration (javax → jakarta) in Boot 3
Explain when to prefer constructor injection + final fields (eliminates the @PostConstruct need), discuss that @PreDestroy only runs on graceful shutdown (not kill -9), and mention the Boot 3 jakarta.annotation migration
Interview-ready guide
Interview answer
@PostConstruct and @PreDestroy exist because constructors and finalizers cannot reliably handle initialization and cleanup in a dependency-injected world.
Why the constructor is not enough
- With field injection,
@Autowiredfields are null inside the constructor — they have not been injected yet @PostConstructruns after all injection is complete — the correct place to warm caches, validate configuration, open connections- Constructor injection with
finalfields often eliminates the need for@PostConstructentirely — dependencies are available from line one
Callback order when all three exist on one bean
@PostConstructfires first — JSR-250 standard, works in any Jakarta EE containerInitializingBean.afterPropertiesSet()fires second — Spring's older interface approach; avoid in new code@Bean(initMethod = "setup")fires last — for third-party classes you cannot annotate
Failure modes that matter
- If
@PostConstructthrows, the context refuses to start — by design - Keep
@PostConstructlogic idempotent and failure-aware; avoid blocking network calls without timeouts
`@PreDestroy` — cleanup on shutdown
- Runs on singleton beans in reverse creation order when
ApplicationContext.close()is called (SIGTERM,docker stop, Kubernetes graceful termination) - Never called on SIGKILL — never store critical state in
@PreDestroy, only release local resources - Never called on prototype beans — switching a singleton to prototype scope without adding explicit cleanup leaks connections and threads silently
Jakarta migration in Spring Boot 3
- Imports moved from
javax.annotation.PostConstructtojakarta.annotation.PostConstruct - For new projects on Boot 3+, use the Jakarta imports
Ordering when constructor-DI isn't enough
@DependsOn("flywayMigrator")forces Spring to create the named bean first — useful for runtime-only dependencies like Flyway before JPA
@PostConstruct and @PreDestroy — Bean Initialization and Destruction Callbacks
Direct Answer
@PostConstruct marks a method Spring calls after the bean is fully constructed and all dependencies are injected — the safe place for initialization logic that uses @Autowired collaborators (the constructor can't, for field injection). @PreDestroy marks a method called when the container shuts down — close resources, flush caches, stop schedulers. Callback order on a single bean: @PostConstruct → InitializingBean.afterPropertiesSet() → custom @Bean(initMethod="..."). Destruction mirrors in reverse, in reverse bean-creation order. Critical gotcha: @PreDestroy never fires on prototype beans — Spring creates them but doesn't track them after creation. In Jakarta EE migration (Spring Boot 3+), imports moved from javax.annotation to jakarta.annotation.
Common Mistakes & Pitfalls
Using @PostConstruct to initialize state that could go in the constructor; assuming @PreDestroy runs on prototype beans; forgetting the Jakarta migration (javax → jakarta) in Boot 3
Check your understanding
Answer these without looking back at the article.
- Why is constructor injection with `final` fields often better than @PostConstruct?
- What happens if @PostConstruct throws an exception?
- Why doesn't @PreDestroy run on prototype beans?
- When does @PreDestroy NOT run even for singletons (e.g., SIGKILL)?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.