Spring Bean life cycle

CodesCoddler
3 min readMar 12, 2024

In Spring Boot, the bean lifecycle is managed by the Spring container. It refers to the sequence of steps that a Spring bean goes through from its instantiation to its destruction.

Here are the main stages:

  1. Instantiation: This is the first step where the Spring container creates an instance of the bean.
  2. Populate Properties: The Spring container injects the dependencies specified in the bean definition.
  3. BeanNameAware Interface: If the bean implements the BeanNameAware interface, Spring passes the bean's ID to setBeanName() method.
  4. BeanFactoryAware Interface: If the bean implements the BeanFactoryAware interface, Spring passes the beanFactory instance to the bean.
  5. ApplicationContextAware Interface: If the bean implements the ApplicationContextAware interface, Spring passes the applicationContext instance to the bean.
  6. PreInitialization — BeanPostProcessors: Before initialization, the postProcessBeforeInitialization() method of all registered BeanPostProcessors is called.
  7. Initialization: The Spring container calls the afterPropertiesSet() method of the InitializingBean interface. If the bean has a custom init method, that is also called.
  8. PostInitialization — BeanPostProcessors: After initialization, the postProcessAfterInitialization() method of all registered BeanPostProcessors is called.
  9. Bean is Ready for Use: Now, the bean is ready to be used by the application.
  10. DisposableBean Interface: If the bean implements the DisposableBean interface, Spring will call the destroy() method during the shutdown of the Spring container.
  11. Custom Destroy Method: If a custom destroy method is defined, Spring will call that method during the shutdown of the Spring container.

It’s important to note that Spring Boot simplifies this process by auto-configuring many beans for you, based on what it sees on the classpath, what beans you have defined, and the settings in your application.properties or application.yml file.

Let’s discuss some practical use cases for each stage of the Spring Boot bean lifecycle:

Instantiation: Let’s say we have a UserService class. The Spring container will create an instance of this class during this stage.

@Service
public class UserService {
//...
}

Populate Properties: If UserService has a dependency on UserRepository, Spring will inject this dependency.

@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
//...
}

BeanNameAware Interface: If UserService implements BeanNameAware, it can get its own bean name from the Spring container.

@Service
public class UserService implements BeanNameAware {
//...
@Override
public void setBeanName(String name) {
System.out.println("Bean name is: " + name);
}
}

BeanFactoryAware Interface: If UserService implements BeanFactoryAware, it can get the bean factory that created it.

@Service
public class UserService implements BeanFactoryAware {
//...

@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
// use beanFactory
}
}

ApplicationContextAware Interface: If UserService implements ApplicationContextAware, it can get the application context that it's running in.

@Service
public class UserService implements ApplicationContextAware {
//...

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
// use applicationContext
}
}

PreInitialization — BeanPostProcessors: This can be used to perform operations before a bean is initialized. For example, you can use it to log bean creation.

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Before Initialization: " + beanName);
return bean;
}
}

Initialization: You can use the afterPropertiesSet() method to perform custom initialization logic.

@Service
public class UserService implements InitializingBean {
//...

@Override
public void afterPropertiesSet() throws Exception {
System.out.println("UserService has been initialized");
}
}

PostInitialization — BeanPostProcessors: This can be used to perform operations after a bean is initialized, such as wrapping a bean with a proxy.

Bean is Ready for Use: At this stage, the UserService bean is fully initialized and ready to be used in your application.

DisposableBean Interface: If your bean needs to release resources before it is destroyed, you can do so in the destroy() method.

@Service
public class UserService implements DisposableBean {
//...
@Override
public void destroy() throws Exception {
System.out.println("UserService is being destroyed");
}
}

Custom Destroy Method: You can specify a custom destroy method in your bean using the @PreDestroy annotation. This method will be called when the bean is being destroyed.

@Service
public class UserService {
//...
@PreDestroy
public void cleanup() {
System.out.println("UserService cleanup");
}
}

These examples illustrate how you can use each stage of the Spring Boot bean lifecycle to manage your beans and their dependencies effectively.

--

--