In the Spring framework, a fundamental concept for Java developers is the bean life cycle. This life cycle encompasses several stages, starting with the creation of a bean, followed by its initialization, use during the application's runtime, and finally, its destruction. Managed by the Spring container, this process offers developers the opportunity to inject custom behavior at different phases.

Understanding and effectively managing the bean life cycle is pivotal for creating efficient, robust, and maintainable Spring applications. Let's delve into the ways this life cycle can be implemented and managed within the Spring framework.
The spring bean life cycle is shown in the diagram below:

Why Understand the Spring Bean Life Cycle?
Understanding the Spring Bean life cycle is crucial for developers working with the Spring Framework as it provides insights into how Spring manages and initializes beans. Knowledge of the bean life cycle enables developers to customize bean initialization, destruction, and behavior, allowing for more efficient resource management, dependency injection, and integration of third-party libraries within Spring applications.
Ways to Implement the Life Cycle of a Bean
The life cycle of a bean in Spring can be implemented using initialization and destruction callbacks. Developers can define methods annotated with @PostConstruct and @PreDestroy for custom initialization and cleanup tasks, ensuring proper initialization and disposal of beans managed by the Spring container.
1. By XML Configuration
In this approach, the bean's life cycle methods are defined in an XML configuration file. This method involves specifying init-method and destroy-method attributes in the bean definition. The Spring container will call these methods at the appropriate life cycle stages.
Code Example:
XML Configuration (beans.xml):
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myBean" class="com.example.MyBean" init-method="init" destroy-method="cleanup">
<!-- Bean properties -->
</bean>
</beans>
Java Class (MyBean.java):
package com.example;
public class MyBean {
public void init() {
System.out.println("MyBean is initialized via XML.");
}
public void cleanup() {
System.out.println("MyBean is destroyed via XML.");
}
}
Advantages:
-
Clear separation of configuration from Java code.
- Suitable for projects where XML-based configuration is preferred or legacy projects.
2. By Programmatic Approach
Explanation:
This approach uses the InitializingBean and DisposableBean interfaces provided by Spring. Implementing these interfaces allows defining afterPropertiesSet() and destroy() methods, respectively, providing explicit control over bean initialization and destruction.
Code Example:
Java Class Implementation (MyBean.java):
package com.example;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class MyBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("MyBean is initialized via InitializingBean.");
}
@Override
public void destroy() throws Exception {
System.out.println("MyBean is destroyed via DisposableBean.");
}
}
Advantages:
- Direct control over the initialization and destruction process.
- More explicit and programmatic, which can be preferable in Java-configured applications.
3. Using Annotations
Explanation:
Annotation-based configuration uses @PostConstruct and @PreDestroy annotations. These annotations are used to mark methods that should be executed after the bean is initialized and before it is destroyed, respectively. This approach aligns with modern Spring practices.
Code Example:
Java Class with Annotations (MyBean.java):
package com.example;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBean {
@PostConstruct
public void init() {
System.out.println("MyBean is initialized via @PostConstruct.");
}
@PreDestroy
public void cleanup() {
System.out.println("MyBean is destroyed via @PreDestroy.");
}
}
Advantages:
- Simplicity and minimal boilerplate.
- Enhances readability and maintainability of the code.
Also Read, spring mvc vs spring boot