How does @DependsOn affect bean destruction order at container shutdown?
answer
- destroy = reverse of create
- depended-on bean destroyed LAST
- keep collaborator alive during teardown
- created first ⇒ destroyed last
- prototypes: container doesn't destroy
basics
~10 sDestruction is the reverse of creation. If A @DependsOn B, then B is created before A, so at shutdown A is destroyed before B. The depended-on bean is torn down last.
solid answer
~40 s@DependsOn controls both ends of the lifecycle. On startup it guarantees the named beans are initialized first; on shutdown the container reverses that order, so the dependent bean is destroyed BEFORE the beans it depends on. Intuitively: because A relied on B being present, B must remain available while A tears down, then B goes last. This matters when destroy callbacks (@PreDestroy, DisposableBean.destroy, destroy-method) use the depended-on bean's side effect — e.g. A flushes to a resource that B set up, so B must still be alive during A's shutdown. Only container-managed singletons participate in orderly destruction; prototype-scoped beans are not destroyed by the container, so destruction ordering doesn't apply to them.
code
java · 14 lines@Component("connectionPool")
class ConnectionPool {
@PostConstruct void open() { /* startup: runs 1st */ }
@PreDestroy void close() { /* shutdown: runs 2nd (last) */ }
}
@Component
@DependsOn("connectionPool")
class AuditWriter {
@PostConstruct void init() { /* startup: runs 2nd */ }
@PreDestroy void flush() { /* shutdown: runs 1st — pool still open here */ }
}
// Init order : connectionPool -> auditWriter
// Destroy order: auditWriter -> connectionPool (reverse)go deeper
Just remember destruction is the reverse of creation.
Explain why reverse order is safe (collaborator still alive during teardown) and name the destroy callbacks.
Tie it to the general reverse-destruction rule and the prototype non-management caveat.
Discuss shutdown correctness for resource-holding beans and how ordering prevents use-after-close in @PreDestroy.
## Symmetry of the lifecycle `@DependsOn` establishes a directed edge in the container's dependency graph. Spring uses that graph in **both** directions: - **Initialization (startup):** depended-on beans first. If `A @DependsOn B`, Spring creates and fully initializes `B` before `A`. - **Destruction (shutdown):** exactly the reverse. `A` is destroyed **before** `B`. The bean that was created *last* is destroyed *first*. ## Why reverse order is the correct default Destruction reversal is a general Spring rule (it applies to injection dependencies too, not just `@DependsOn`). The reasoning: if `A` depended on `B` existing, then `A`'s teardown logic may still need `B`. Destroying `B` first could leave `A`'s `@PreDestroy` calling into an already-destroyed collaborator. So the depended-on bean is kept alive until everything that depends on it is gone. ### Concrete example `connectionPool` opens resources; `auditWriter @DependsOn("connectionPool")` writes a final audit record in `@PreDestroy`. Startup: pool first, writer second. Shutdown: writer's `@PreDestroy` runs first (pool still open, write succeeds), then the pool closes. Reverse order prevents a use-after-close. ## The callbacks involved Destruction callbacks that fire in this ordered fashion: - `@PreDestroy` (JSR-250) - `DisposableBean.destroy()` - a custom `destroyMethod` (on `@Bean(destroyMethod=...)` or XML `destroy-method`) They are invoked by `DefaultListableBeanFactory` / `DefaultSingletonBeanRegistry` during `context.close()` (or the registered JVM shutdown hook). ## Scope caveats - **Singletons:** fully managed — orderly, reverse-order destruction with `@DependsOn` honored. This is the normal case. - **Prototype beans:** Spring instantiates and hands them off but does **not** manage their destruction — no destroy callbacks are called by the container. So destruction ordering is moot for prototypes even if `@DependsOn` is present (init ordering still applies when the prototype is created). - **Web scopes (request/session):** destroyed at end of the request/session, again in reverse of creation within that scope. ## Gotcha People remember the startup half ('B before A') and forget the shutdown half. In an interview, state both directions explicitly: **created first ⇒ destroyed last.**
- Do prototype-scoped beans get their @DependsOn destruction ordering honored?No. Spring does not manage the destruction lifecycle of prototype beans at all — no destroy callbacks are invoked by the container — so destruction ordering doesn't apply. Initialization ordering still applies when the prototype instance is created.
- Is reverse destruction order unique to @DependsOn?No. It's the general container rule: beans are destroyed in reverse of their initialization dependency order, whether the edge came from injection or from @DependsOn.
saying these in an interview costs you the question
- Claiming the depended-on bean is destroyed first (it's destroyed last).
- Assuming prototype beans get destroy callbacks from the container.
- Thinking @DependsOn only affects startup, not shutdown.