Bean Lifecycle
Description
The Spring Bean Lifecycle refers to the well-defined stages a bean goes through in a Spring application, from its creation to its eventual destruction. This lifecycle is managed by the Spring IoC container (BeanFactory) and ensures proper initialization, configuration, and cleanup of beans.
Benefits of Managed Bean Lifecycle:
Simplified Development: Spring handles the complexities of bean creation, configuration, and destruction, allowing us to focus on core application logic.
Consistency and Predictability: Ensures consistent initialization and cleanup behavior across all beans in Spring application.
Improved Testability: By separating bean configuration from bean logic, Spring facilitates easier unit testing of beans.
Stages
1. Bean Instantiation:
The first step in the bean lifecycle is the instantiation of the bean. This occurs when the Spring IoC container reads the bean definition and creates an instance of the bean (corresponding class) based on the configuration metadata provided (e.g., XML configuration, Java annotations, or Java-based configuration). This instantiation can happen through various mechanisms depending on the bean scope (singleton, prototype, etc.).
During this stage, the container creates a new instance of the bean by invoking its constructor. The primary purpose of this stage is to prepare the bean for further initialization.
2. Bean Population (Property Setting):
After creating the bean instance, Spring populates its properties with values. This involves, Injecting dependencies using constructor injection or setter injection or field injection(based on configuration) and Setting bean properties defined in the configuration file.
3. BeanNameAware: Giving Identity to the Bean
After instantiation, the bean becomes aware of its assigned name within the Spring container. The BeanNameAware
interface in Spring provides a way for a bean to be aware of its own bean name, i.e., the identifier used to reference it within the Spring IoC container. Implementing the BeanNameAware
interface allows a bean to obtain its assigned bean name during initialization.
4. BeanFactoryAware and ApplicationContextAware: Utilizing Context
The next stage involves the bean gaining awareness of the bean factory or application context it’s part of. This awareness fosters interaction with other beans and resources within the context. It is used when access global context and resources is needed.
Both the BeanFactoryAware
and ApplicationContextAware
interfaces in Spring provide a way for a bean to gain access to the Spring IoC container in which it is managed. They allow the bean to interact with the container programmatically, gaining access to the container's features and resources.
BeanFactoryAware Interface:
The BeanFactoryAware
interface is used by beans that need access to the Spring BeanFactory that manages them. When a bean implements this interface, Spring automatically injects the BeanFactory instance into the bean before it is initialized.
ApplicationContextAware Interface:
The ApplicationContextAware
interface is used by beans that need access to the ApplicationContext, which is a specialization of the BeanFactory interface. ApplicationContext provides additional features such as internationalization, event propagation, application context hierarchy, and more. When a bean implements this interface, Spring injects the ApplicationContext instance into the bean before it is initialized.
5. Bean Post-Processing (Initialization Callbacks):
Once the properties are set, the container calls any registered BeanPostProcessors to perform any necessary post-processing on the bean instance. BeanPostProcessors allow for custom modifications to bean instances before and after initialization. These are beans that can intercept the lifecycle of other beans and perform additional logic before or after initialization. Two important methods defined in BeanPostProcessor interface are postProcessBeforeInitialization()
and postProcessAfterInitialization()
.
6. Customizing Bean Initialization:
After the post-processing phase, the container calls the bean's initialization callbacks to perform custom initialization logic. This can be achieved through:
Implementing the
InitializingBean
interface (org.springframework.beans.factory.InitializingBean) and overriding theafterPropertiesSet()
method.Specifying an initialization method using the
init-method
attribute in XML configuration or@PostConstruct
annotation (javax.annotation.PostConstruct) in Java configuration.
It’s useful when you need to perform specific actions on the bean right after it’s initialized, such as configuring properties or performing last-minute preparations. One of the use-case can be like after a pod restart, we might want to delete temporary data or expired records from the database or reload cache data from the database to ensure a clean state.
Also, this stage provides an opportunity for executing custom setup logic after properties are set and before the bean is ready for use.
7. Custom Initialization: For Special Scenario
In some scenarios, the need arises for specialized initialization steps that go above standard setup. This is where custom initialization methods helps.
8. Bean Ready for Use:
At this stage, bean is fully initialized and configured, it's ready to be used by other parts of application. Spring manages bean creation and retrieval through its dependency injection mechanisms.
9. Bean Destruction:
When the application context is shut down or when the bean is no longer needed, the container calls the bean's destruction callbacks. Destruction callbacks can be implemented by:
Implementing the
DisposableBean
interface and overriding thedestroy()
method.Specifying a destruction method using the
destroy-method
attribute in XML configuration or@PreDestroy
annotation in Java configuration.
The destruction callbacks are used to perform any cleanup tasks required by the bean before it's destroyed, such as releasing resources or closing connections.
When to Use:
Use
@PreDestroy
when we want to define destruction logic in a declarative way using annotations, especially in Java EE or Spring applications.Use
DisposableBean
when we need to implement destruction logic programmatically and don't mind the tight coupling with the Spring framework.
Additional dependency will be needed to include in pom.xml for javax annotations
Not all stages are mandatory. For instance, a bean might not require custom initialization or destruction logic.
Example
Structure
pom.xml dependency
Classes and Methods declaration
Item class
MyBean class
MyBeanConfig class
MyBeanPostProcessor class
Main Application class
Run the application and verify the output
FAQs
Can I use constructor injection and setter injection in the same bean?
Yes, we can combine constructor injection and setter injection in the same bean, allowing to set mandatory properties through the constructor and optional properties using setter methods.
What happens if a bean fails to initialize during the application startup process?
If a bean fails to initialize (e.g., due to an exception), Spring usually stops the application startup and provides error messages or exceptions that indicate the problem.
Can I use AOP (Aspect-Oriented Programming) with Spring Bean life cycle methods?
Yes, we can use AOP to apply aspects (cross-cutting concerns) before, after, or around Spring Bean life cycle methods, enabling you to add custom behaviour such as logging or security checks.
Are there any performance considerations when using Spring Bean life cycle methods extensively?
Extensive use of life cycle methods can affect application startup time. Best to avoid performing costly operations during initialization.
Last updated