Skip to main navigation Skip to main content Skip to page footer

Spring Core - Spring Bean Lifecycle

| Java Spring Boot

The Spring Bean Lifecycle defines the sequence of events that occur during the creation, initialization, and destruction of a bean managed by the Spring container. Understanding this lifecycle is essential for managing resources and ensuring proper initialization and cleanup of beans.

Lifecycle Phases

  1. Bean Instantiation
    • The Spring container instantiates the bean by calling its constructor or a static factory method.
  2. Populate Properties (Dependency Injection)
    • The container injects values into the bean's properties, typically through setter methods or constructor arguments.
  3. Bean Name and Factory Aware Callbacks (Optional)
    • If the bean implements specific interfaces (e.g., BeanNameAware, BeanFactoryAware), the container will call the corresponding methods to provide context (e.g., bean name or reference to the BeanFactory).
  4. Bean Initialization
    • Pre-initialization: The container applies BeanPostProcessors before the initialization method.
    • Custom Initialization: If specified, the initialization logic is executed (e.g., methods annotated with @PostConstruct or declared via init-method).
    • Post-initialization: The container applies BeanPostProcessors after the initialization method.
  5. Bean Ready for Use
    • The bean is now fully initialized and ready to be used within the application.
  6. Bean Destruction
    • Before the container destroys a bean (e.g., during shutdown), it executes any destruction logic (e.g., methods annotated with @PreDestroy or declared via destroy-method).

Diagram of the Spring Bean Lifecycle

1. Instantiate Bean

2. Dependency Injection (populate properties) 
↓ 
3. Aware Interfaces (if implemented) 
↓ 
4. BeanPostProcessor (Before Initialization) 
↓ 
5. Initialization (e.g., @PostConstruct, init-method) 
↓ 
6. BeanPostProcessor (After Initialization) 
↓ 
7. Bean Ready for Use 
↓ 
8. Destruction (e.g., @PreDestroy, destroy-method)

Lifecycle Methods and Hooks

1. Using @PostConstruct and @PreDestroy

Annotate methods for initialization and cleanup tasks.

@Component
public class MyBean {

    @PostConstruct
    public void init() {
        System.out.println("Bean is initialized!");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Bean is being destroyed!");
    }
}

2. Implementing Lifecycle Interfaces

  • InitializingBean: Define custom initialization logic in the afterPropertiesSet() method.
  • DisposableBean: Define custom destruction logic in the destroy() method.
@Component
public class MyBean implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() {
        System.out.println("Custom initialization logic in afterPropertiesSet()");
    }

    @Override
    public void destroy() {
        System.out.println("Custom cleanup logic in destroy()");
    }
}

3. Using @Bean with initMethod and destroyMethod

Lifecycle methods can be directly defined in a @Configuration class.

@Configuration
public class AppConfig {

    @Bean(initMethod = "customInit", destroyMethod = "customDestroy")
    public MyBean myBean() {
        return new MyBean();
    }
}

public class MyBean {
    public void customInit() {
        System.out.println("Custom initialization logic");
    }

    public void customDestroy() {
        System.out.println("Custom destruction logic");
    }
}

4. Using BeanPostProcessor

Bean creation can be intercepted for applying custom logic before or after initialization.

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("Before Initialization: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("After Initialization: " + beanName);
        return bean;
    }
}

Best Practices

  • Use @PostConstruct and @PreDestroy for simple lifecycle management.
  • Prefer initMethod and destroyMethod for reusable beans.
  • Use BeanPostProcessor sparingly for cross-cutting concerns.
  • Avoid heavy initialization in constructors - use lifecycle methods instead.
  • Always release resources during destruction to avoid memory leaks.
Back