keepcalculator

06 Numbers and Powers

Spring Bean Lifecycle: Creation to Destruction

Card No. 06·4112 · Updated · Standard formula, shown below

Avg time per day (ms) 3.33 ms
Total lifetime (days)
30 days
You entered
Startup time (ms)
100 ms
You entered
You enter
Total lifetime (days), Startup time (ms)
You get
Avg time per day (ms)
Rounding
2 dp

The Spring bean lifecycle describes the journey of a bean from its instantiation and dependency injection through initialization and use, up to its destruction and cleanup. This article walks through each stage in order, explains the hooks Spring provides for custom behavior, and answers common questions about how to manage bean lifecycles in real applications.

What Is a Spring Bean?

A Spring bean is an object that is instantiated, assembled, and managed by the Spring IoC (Inversion of Control) container. Instead of using new to create objects, you declare them in configuration (XML, Java config, or annotations), and the container takes responsibility for their entire lifecycle—from creation to destruction. This centralization lets you apply cross-cutting concerns like proxying, scoping, and lifecycle callbacks consistently across all beans.

Stage 1: Instantiation

The container reads your configuration metadata and creates the bean’s instance. For a typical singleton bean, this happens once when the container starts. For prototype beans, it happens every time you request the bean from the container. Instantiation is usually done via a constructor, but Spring also supports static factory methods and instance factory methods. During this stage, the bean is just a raw object—no properties have been set yet.

Stage 2: Populating Properties

After instantiation, Spring populates the bean’s properties and dependencies. This includes:

  • Setter injection: Spring calls setter methods on the bean.
  • Field injection: Spring directly sets annotated fields (e.g., @Autowired).
  • Constructor injection: If you use constructor injection, the dependencies are passed during instantiation, so this stage is merged with the previous one.

If any required dependency is missing, the container throws an exception and the bean fails to initialize.

Stage 3: Aware Interfaces

If the bean implements any of Spring’s Aware interfaces, the container calls the corresponding setter to give the bean access to Spring infrastructure. Common examples:

  • BeanNameAware – sets the bean’s name as defined in the configuration.
  • BeanFactoryAware – gives the bean a reference to its owning BeanFactory.
  • ApplicationContextAware – gives the bean a reference to the ApplicationContext.

These callbacks happen before initialization, so you can use them to store context information that you’ll need later.

Stage 4: Initialization

Initialization is where you can add custom logic that must run after the bean’s dependencies are set. Spring provides several mechanisms, in order of precedence:

  1. @PostConstruct annotated method (or init-method in XML, or afterPropertiesSet() from InitializingBean). The @PostConstruct method is the most commonly used and is executed after dependency injection.
  2. BeanPostProcessor hooks: postProcessBeforeInitialization and postProcessAfterInitialization wrap the initialization step, letting you modify or wrap the bean instance.

For example, a database connection pool might open its connections in @PostConstruct. This is the stage where the bean is fully ready for use.

Stage 5: Ready for Use

After initialization, the bean sits in the container and is handed out to other beans or to your application code via getBean() or dependency injection. For singletons, the same instance is returned every time. For prototypes, a new instance is created per request—but note that Spring does not manage the destruction of prototype beans; the caller is responsible for cleanup.

Stage 6: Destruction

When the application context shuts down, singleton beans go through destruction callbacks. The order is:

  1. If the bean implements DisposableBean, its destroy() method is called.
  2. If you declared destroy-method in XML or @PreDestroy in annotations, that method is invoked.

This is where you release resources: close database connections, stop threads, or flush caches. Prototype beans do not receive destruction callbacks because the container no longer tracks them after creation.

Scopes and Lifecycle

The lifecycle described above applies fully to singleton beans, which are the default. Other scopes have variations:

  • Prototype: Instantiation, property population, and initialization happen per request; destruction callbacks are skipped.
  • Request, session, application, and websocket scopes: These are available in web-aware contexts. The container manages their lifecycle relative to the HTTP request or session, and destruction happens when the scope ends.

Understanding scope is crucial because it determines how many instances exist and when cleanup occurs. For example, a prototype bean that opens a file handle will leak that handle unless you explicitly close it.

Common Misconception: init-method vs. @PostConstruct

Many developers wonder which initialization method to use. @PostConstruct is part of the Java EE standard (javax.annotation), while init-method is a Spring-specific XML attribute. In modern Spring, @PostConstruct is preferred because it’s annotation-based and works with component scanning. However, if you’re using XML configuration, init-method is the natural choice. Both are called after property population, so the bean is fully wired when they execute.

Frequently Asked Questions

What is the order of bean lifecycle callbacks?

The order is: instantiation → property population → Aware callbacks (e.g., BeanNameAware) → @PostConstruct / afterPropertiesSet() → BeanPostProcessor.postProcessBeforeInitialization → BeanPostProcessor.postProcessAfterInitialization → ready for use → @PreDestroy / destroy() on shutdown.

Do prototype beans get destroyed by Spring?

No. Spring does not call destruction callbacks on prototype beans because the container doesn’t keep a reference after creation. You must clean up resources manually, for example by implementing AutoCloseable and using try-with-resources in your code.

Can I use both @PostConstruct and init-method on the same bean?

Yes, you can, and both will be called. The @PostConstruct method runs first, followed by the init-method (if specified). However, doing so is usually redundant; pick one approach for clarity.

What happens if a bean’s @PostConstruct method throws an exception?

The bean is considered failed, and the container will not expose it. For singletons, this typically prevents the application context from starting successfully. The exception propagates to the caller that triggered the context refresh.

How can I run custom logic after all beans are initialized?

Implement ApplicationListener<ContextRefreshedEvent> or use @EventListener(ApplicationReadyEvent.class) on a method. This runs after the entire context is fully started, so you can safely access any bean.

Related

Formula used
in t | Total lifetime (days) | days | 30 | 0 | 3650
in s | Startup time (ms) | ms | 100 | 0 | 60000
out avg | Avg time per day (ms) | ms | s / t | 2

Each line is one input (in, sel, list) or one result (out: label, unit, formula, decimals). How the calculators work

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →