1. Overview

In this tutorial, we’re going to learn different ways to use shutdown callbacks with Spring.

The main advantage of using a shutdown callback is that it gives us control over a graceful application exit.

2. Shutdown Callback Approaches

Spring supports both the component-level and the context-level shutdown callbacks. We can create these callbacks using:

  • @PreDestroy
  • DisposableBean interface
  • Bean-destroy method
  • Global ServletContextListener

Let’s see all of these approaches with examples.

2.1. Using @PreDestroy

Let’s create a bean that uses @PreDestroy:

@Component
public class Bean1 {

    @PreDestroy
    public void destroy() {
        System.out.println(
          "Callback triggered - @PreDestroy.");
    }
}

During the bean initialization, Spring will register all the bean methods that are annotated with @PreDestroy and invokes them when the application shuts down.

2.2. Using the DisposableBean Interface

Our second bean will implement the DisposableBean interface to register the shutdown callback:

@Component
public class Bean2 implements DisposableBean {

    @Override
    public void destroy() throws Exception {
        System.out.println(
          "Callback triggered - DisposableBean.");
    }
}

2.3. Declaring a Bean Destroy Method

For this approach, firstly we’ll create a class with a custom destroy method:

public class Bean3 {

    public void destroy() {
        System.out.println(
          "Callback triggered - bean destroy method.");
    }
}

Then, we create the configuration class that initializes the bean and marks its destroy() method as our shutdown callback:

@Configuration
public class ShutdownHookConfiguration {

    @Bean(destroyMethod = "destroy")
    public Bean3 initializeBean3() {
        return new Bean3();
    }
}

The XML way of registering the destroy method is:

<bean class="com.baeldung.shutdownhooks.config.Bean3"
  destroy-method="destroy">

2.4. Using a Global ServletContextListener

Unlike the other three approaches, which register the callback at bean level, the ServletContextListener registers the callback at context level.

For this let’s create a custom context listener:

public class ExampleServletContextListener
  implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent event) {
        System.out.println(
          "Callback triggered - ContextListener.");
    }

    @Override
    public void contextInitialized(ServletContextEvent event) {
        // Triggers when context initializes
    }
}

We need to register it to the ServletListenerRegistrationBean in the configuration class:

@Bean
ServletListenerRegistrationBean<ServletContextListener> servletListener() {
    ServletListenerRegistrationBean<ServletContextListener> srb
      = new ServletListenerRegistrationBean<>();
    srb.setListener(new ExampleServletContextListener());
    return srb;
}

3. Conclusion

We’ve learned about the different ways Spring provides to register shutdown callbacks, both at the bean level and at the context level.

These can be used for shutting down the application gracefully and effectively freeing up the used resources.

As always all the examples mentioned in this article can be found over on Github.