Spring Framework Tutorial

Software Setup and Configuration (STS/Eclipse/IntelliJ)

Core Spring

Spring Annotations

Spring Data

Spring JDBC

Spring Security

Bean life cycle in Java Spring

In the Spring Framework, beans are the objects that form the backbone of the application. Spring's Inversion of Control (IoC) container is responsible for the creation, initialization, wiring, and destruction of beans. A bean's life cycle in Spring is a sequence of steps from its instantiation to its destruction. Here's an overview of the life cycle:

  1. Instantiation: A bean is created based on its definition in the Spring configuration file.

  2. Populate properties: Once the bean is instantiated, the properties specified in the bean definition are set in the bean.

  3. Setting Bean Name: If the bean implements the BeanNameAware interface, the setBeanName() method is called, setting the bean name.

  4. ApplicationContextAware: If a bean implements the ApplicationContextAware interface, it's provided with the application context by calling its setApplicationContext() method.

  5. BeanPostProcessors: Before the bean's initialization method is invoked, any BeanPostProcessor beans are called. They can perform operations on the bean.

  6. Initialization: If a bean implements the InitializingBean interface, its afterPropertiesSet() method is called. If an init-method is specified in the bean definition, that method is also called.

  7. Custom Initialization Methods: If the bean has custom initialization methods, these are executed at this stage.

  8. Bean is ready for use: At this point, the bean is fully initialized and ready to be used in the application.

  9. BeanPostProcessors (after initialization): After the initialization of the bean, any BeanPostProcessor beans can perform operations on the bean.

  10. Destruction: If the context is a ConfigurableApplicationContext, it has a close() method. When this method is called, or when the application stops, the beans are destroyed. If a bean implements the DisposableBean interface, its destroy() method is called. If a destroy-method is specified in the bean definition, that method is also executed.

This lifecycle ensures that beans are created, initialized, and managed by the Spring container in a consistent manner. Developers can also tap into various points in the life cycle to add custom behavior.

To take control of these lifecycle events, Spring provides the following mechanisms:

  • InitializingBean and DisposableBean interfaces for bean initialization and destruction callbacks respectively.

  • Custom init and destroy methods (using the init-method and destroy-method attributes in the XML configuration or @PostConstruct and @PreDestroy annotations).

  • BeanPostProcessor interfaces which give a means to tap into the lifecycle events and can modify beans, properties, or perform specific actions.

In a modern Spring application with Java-based configuration, beans and their lifecycles are often managed using annotations like @Component, @Service, @Repository, @Controller, @PostConstruct, and @PreDestroy.

  1. How to Implement InitializingBean and DisposableBean Interfaces in Spring:

    • Description: The InitializingBean and DisposableBean interfaces allow beans to define custom initialization and destruction methods.
    • Code:
      import org.springframework.beans.factory.DisposableBean;
      import org.springframework.beans.factory.InitializingBean;
      
      public class MyBean implements InitializingBean, DisposableBean {
      
          @Override
          public void afterPropertiesSet() throws Exception {
              // Custom initialization logic
              System.out.println("Bean initialized");
          }
      
          @Override
          public void destroy() throws Exception {
              // Custom destruction logic
              System.out.println("Bean destroyed");
          }
      }
      
  2. @PostConstruct and @PreDestroy Annotations in Spring Beans:

    • Description: Annotations @PostConstruct and @PreDestroy allow specifying methods for bean initialization and destruction without implementing specific interfaces.
    • Code:
      import javax.annotation.PostConstruct;
      import javax.annotation.PreDestroy;
      
      public class MyBean {
      
          @PostConstruct
          public void init() {
              // Custom initialization logic
              System.out.println("Bean initialized");
          }
      
          @PreDestroy
          public void cleanUp() {
              // Custom destruction logic
              System.out.println("Bean destroyed");
          }
      }
      
  3. Customizing Bean Life Cycle with BeanPostProcessor in Spring:

    • Description: BeanPostProcessor interface allows customizing the bean's life cycle by providing pre- and post-processing hooks.
    • Code:
      import org.springframework.beans.BeansException;
      import org.springframework.beans.factory.config.BeanPostProcessor;
      
      public class CustomBeanPostProcessor implements BeanPostProcessor {
      
          @Override
          public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
              // Custom pre-initialization logic
              return bean;
          }
      
          @Override
          public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
              // Custom post-initialization logic
              return bean;
          }
      }
      
  4. XML Configuration for Spring Bean Life Cycle:

    • Description: XML configuration allows specifying init-method and destroy-method attributes to define custom initialization and destruction methods.
    • Code:
      <bean id="myBean" class="com.example.MyBean" init-method="init" destroy-method="cleanUp"/>
      
  5. Annotated Configuration for Spring Bean Life Cycle:

    • Description: Annotations such as @Bean and @Configuration can be used for Java-based configuration, and @Lazy for lazy initialization.
    • Code:
      @Configuration
      public class AppConfig {
      
          @Bean(initMethod = "init", destroyMethod = "cleanUp")
          public MyBean myBean() {
              return new MyBean();
          }
      }