skip to content

How does @DependsOn affect bean destruction order at container shutdown?

level: middleimportance: should knowfreq 40%

answer

  1. destroy = reverse of create
  2. depended-on bean destroyed LAST
  3. keep collaborator alive during teardown
  4. created first ⇒ destroyed last
  5. prototypes: container doesn't destroy

basics

~10 s

Destruction 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
java
@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

for a junior

Just remember destruction is the reverse of creation.

for a middle

Explain why reverse order is safe (collaborator still alive during teardown) and name the destroy callbacks.

for a senior

Tie it to the general reverse-destruction rule and the prototype non-management caveat.

for a principal

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.

context