Spring Boot (and Spring Framework in general) manages the lifecycle of beans using the Inversion of Control (IoC) Container, which creates, configures, and manages the entire lifecycle of objects (called beans). Understanding the Bean Lifecycle is essential for developers who want to hook into certain phases of a bean’s existence, such as initialization or destruction, to perform custom logic.
1. What is a Bean in Spring Boot?
In Spring Boot, any object that is managed by the Spring container is called a bean. Beans are created, initialized, and destroyed by the Spring IoC container.
Beans are typically created using:
@Component,@Service,@Repository, or@Controllerannotations, or- Defined in configuration classes using
@Beanannotation.
2. Complete Bean Lifecycle Phases
The full lifecycle of a Spring bean involves multiple phases:
- Instantiation – Bean object is created.
- Populate Properties – Dependencies are injected (via constructor or setter injection).
- Bean Name Awareness – Bean can be made aware of its name.
- Bean Factory Awareness – Bean can interact with BeanFactory.
- Application Context Awareness – Bean can access ApplicationContext.
- Pre-initialization Processing – Before initialization hook.
- Initialization – Custom initialization logic is executed.
- Post-initialization Processing – After initialization hook.
- Usage – Bean is ready to be used in the application.
- Destruction – Clean-up before bean is destroyed (when context is closed).
3. Detailed Lifecycle Breakdown
Step 1: Instantiation
Spring first creates an instance of the bean using either:
- Constructor Injection (with
@Autowiredconstructor), or - Default constructor.
Step 2: Dependency Injection
Spring performs Dependency Injection by populating fields marked with @Autowired or by using constructor/setter injection.
Step 3: Bean Name Awareness
If your bean implements the BeanNameAware interface, Spring calls the setBeanName(String name) method, allowing the bean to know its name in the context.
@Component
public class MyBean implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("Bean name is: " + name);
}
}
Step 4: Bean Factory Awareness
If your bean implements BeanFactoryAware, Spring injects the BeanFactory by calling setBeanFactory(BeanFactory beanFactory).
@Component
public class MyBean implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
System.out.println("BeanFactory has been set");
}
}
Step 5: Application Context Awareness
Beans can access the full application context by implementing ApplicationContextAware.
@Component
public class MyBean implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
System.out.println("ApplicationContext has been set");
}
}
Step 6: Bean Post-Processing (Before Initialization)
Before the bean’s custom initialization logic runs, BeanPostProcessor can modify the bean.
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before Initialization: " + beanName);
return bean;
}
}
Step 7: Custom Initialization
There are multiple ways to run initialization logic after properties are set:
@PostConstructannotation- InitializingBean interface
initMethodin@Beanannotation
Example 1: @PostConstruct
@Component
public class MyBean {
@PostConstruct
public void init() {
System.out.println("MyBean is initialized");
}
}
Example 2: InitializingBean
@Component
public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("InitializingBean's afterPropertiesSet called");
}
}
Example 3: initMethod in @Bean
@Bean(initMethod = "customInit")
public MyBean myBean() {
return new MyBean();
}
public void customInit() {
System.out.println("Custom Init Method called");
}
Step 8: Bean Post-Processing (After Initialization)
postProcessAfterInitialization() is called after initialization, again through BeanPostProcessor.
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After Initialization: " + beanName);
return bean;
}
Step 9: Bean is Ready for Use
At this stage, the bean is fully initialized, injected with dependencies, aware of the Spring context, and ready to serve the application.
Step 10: Bean Destruction
Spring ensures that beans clean up resources when the application context is closed.
Ways to define destruction logic:
@PreDestroyannotation- DisposableBean interface
destroyMethodin@Bean
Example 1: @PreDestroy
@PreDestroy
public void destroy() {
System.out.println("MyBean is about to be destroyed");
}
Example 2: DisposableBean
@Component
public class MyBean implements DisposableBean {
@Override
public void destroy() {
System.out.println("DisposableBean destroy method called");
}
}
Example 3: destroyMethod in @Bean
@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
return new MyBean();
}
public void customDestroy() {
System.out.println("Custom destroy method called");
}
