Spring Boot Actuator - how to add custom logic to /shutdown endpoint

I can think of two ways to perform some logic before shutting down the application:

  1. Registering a Filter, it's a web application after all.
  2. Intercepting the invoke method using the @Before advice

Servlet Filter

Since /shutdown is a Servlet endpoint, you can register a Filter to run before the /shutdown endpoint gets called:

public class ShutdownFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) 
                                    throws ServletException, IOException {
        // Put your logic here
        filterChain.doFilter(request, response);
    }
}

Also don't forget to register it:

@Bean
@ConditionalOnProperty(value = "endpoints.shutdown.enabled", havingValue = "true")
public FilterRegistrationBean filterRegistrationBean() {
    FilterRegistrationBean registrationBean = new FilterRegistrationBean();
    registrationBean.setFilter(new ShutdownFilter());
    registrationBean.setUrlPatterns(Collections.singleton("/shutdown"));

    return registrationBean;
}

Defining an @Aspect

If you send a request to the /shutdown endpoint, assuming the shutdown endpoint is enabled and security does not block the request, the invoke method will be called. You can define an @Aspect to intercept this method call and put your logic there:

@Aspect
@Component
public class ShutdownAspect {
    @Before("execution(* org.springframework.boot.actuate.endpoint.ShutdownEndpoint.invoke())")
    public void runBeforeShutdownHook() {
        // Put your logic here
        System.out.println("Going to shutdown...");
    }
}

Also don't forget to enable the AspectJAutoProxy:

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Application { ... }

And spring-aspects dependency:

compile 'org.springframework:spring-aspects'

When it's invoked, the shutdown endpoint calls close() on the application context. This means that all of the usual mechanisms for running some custom logic during close processing are available.

For example, you could add a bean to the application context that implements DisposableBean or use the destroyMethod attribute of @Bean when you declare a bean via Java config:

@Bean(destroyMethod="whateverYouWant")
public void Foo {
    return new Foo();
}