Close

Spring - Receiving Lifecycle callbacks by using @PostConstruct and @PreDestroy

[Last Updated: Mar 14, 2021]

Spring provides various mechanisms for getting bean lifecycle callbacks. These callbacks are useful to take some specific action at a particular lifecycle stage. It's specially needed at the point when bean is fully initialized and all properties are set.

Following are the differents ways to receive callbacks after bean has initialized and before bean is destroyed:

  1. Using @PostConstruct and @PreDestroy
  2. Using 'initMethod' and 'destroyMethod' of @Bean annotation.
  3. By implementing InitializingBean and DisposableBean

This tutorial shows the example of @PostConstruct and @PreDestroy. The next two tutorials will show other methods of receiving callbacks.

Using @PostConstruct and @PreDestroy

The recommended way to receive initialization/destruction callbacks is by using @PostConstruct and @PreDestroy annotations

package com.logicbig.example;

public class OtherBean {
}
package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class MyBean {
  private OtherBean otherBean;

  public MyBean() {
      System.out.println("MyBean constructor: " + this);
  }

  @PostConstruct
  public void myPostConstruct() {
      System.out.println("myPostConstruct()");
  }

  @Autowired
  public void setOtherBean(OtherBean otherBean) {
      System.out.println("setOtherBean(): " + otherBean);
      this.otherBean = otherBean;
  }

  public void doSomething() {
      System.out.println("doSomething()");
  }

  @PreDestroy
  public void cleanUp() {
      System.out.println("cleanUp method");
  }
}

In above example, we used setter injection, we can instead use field/constructor injection as well, the fields will be fully initialized the time when @PostConstruct method is called.

package com.logicbig.example;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LifeCycleExample {

  @Bean
  public MyBean myBean() {
      return new MyBean();
  }

  @Bean
  public OtherBean otherBean() {
      return new OtherBean();
  }

  public static void main(String[] args) {
      ConfigurableApplicationContext context =
              new AnnotationConfigApplicationContext(LifeCycleExample.class);

      context.registerShutdownHook();

      System.out.println("-- accessing bean --");
      MyBean bean = context.getBean(MyBean.class);
      bean.doSomething();

      System.out.println("-- finished --");
  }
}

Output

MyBean constructor: com.logicbig.example.MyBean@11a4dac4
setOtherBean(): com.logicbig.example.OtherBean@121394b8
myPostConstruct()
-- accessing bean --
doSomething()
-- finished --
cleanUp method

Understanding registerShutdownHook() method

In above example, we used ConfigurableApplicationContext#registerShutdownHook(). This method registers a shutdown hook with the JVM runtime. This hook receives notification on JVM shutdown, at that time it closes the underlying context and calls all @PreDestroy and other standard register destroy methods. If we don't want to use this method then we have to call ConfigurableApplicationContext#close() ourselves at JVM shutdown, otherwise our destroy methods won't get called.

Initialization and destruction lifecycle callbacks Select All Download
  • spring-lifecycle-callbacks-using-annotation
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyBean.java

    See Also