Java Spring Boot 关闭钩子

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26678208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 03:02:54  来源:igfitidea点击:

Spring Boot shutdown hook

javaspring-boot

提问by Abdull

How can I register/add a custom shutdown routine that shall fire when my Spring Boot application shuts down?

如何注册/添加在 Spring Boot 应用程序关闭时应触发的自定义关闭例程?

Scenario: I deploy my Spring Boot application to a Jetty servlet container (i.e., no embedded Jetty). My application uses Logback for logging, and I want to change logging levels during runtime using Logback's MBean JMX configurator. Its documentation states that to avoid memory leaks, on shutdown a specific LoggerContext shutdown method has to be called.

场景:我将 Spring Boot 应用程序部署到 Jetty servlet 容器(即,没有嵌入式 Jetty)。我的应用程序使用 Logback 进行日志记录,我想在运行时使用 Logback 的 MBean JMX 配置器更改日志记录级别。它的文档指出,为了避免内存泄漏,在关闭时必须调用特定的 LoggerContext 关闭方法

What are good ways to listen on Spring Boot shutdown events?

监听 Spring Boot 关机事件的好方法是什么?

I have tried:

我试过了:

public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext cac = SpringApplication.run(Example.class, args);

    cac.addApplicationListener(new ApplicationListener<ContextClosedEvent>() {

        @Override
        public void onApplicationEvent(ContextClosedEvent event) {
            logger.info("Do something");
        }
    });
}

but this registered listener does not get called when the application shuts down.

但是当应用程序关闭时,这个注册的监听器不会被调用。

回答by cfrick

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-exit

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-application-exit

Each SpringApplication will register a shutdown hook with the JVM to ensure that the ApplicationContext is closed gracefully on exit. All the standard Spring lifecycle callbacks (such as the DisposableBean interface, or the @PreDestroy annotation) can be used.

In addition, beans may implement the org.springframework.boot.ExitCodeGenerator interface if they wish to return a specific exit code when the application ends.

每个 SpringApplication 都会向 JVM 注册一个关闭钩子,以确保 ApplicationContext 在退出时正常关闭。可以使用所有标准的 Spring 生命周期回调(例如 DisposableBean 接口或 @PreDestroy 注释)。

此外,如果 bean 希望在应用程序结束时返回特定的退出代码,它们可以实现 org.springframework.boot.ExitCodeGenerator 接口。

回答by Dave Syer

Your listener is registered too late (that line will never be reached until the context has already closed). It should suffice to make it a @Bean.

您的侦听器注册太晚(在上下文关闭之前永远不会到达该行)。让它成为一个@Bean.

回答by harsh.tibrewal

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {

    public static void main(
            String[] args) {
        SpringApplication.run(Application.class,
                              args);
    }

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

 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;

 public class ExampleServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(
        ServletContextEvent sce) {
    // Context Initialised
    }

    @Override
    public void contextDestroyed(
        ServletContextEvent sce) {
       // Here - what you want to do that context shutdown    
   }
}

回答by lizhipeng

have you tried this as mentioned by @cfrick ?

你有没有像@cfrick 提到的那样尝试过这个?

@SpringBootApplication
@Slf4j
public class SpringBootShutdownHookApplication {

  public static void main(String[] args) {
    SpringApplication.run(SpringBootShutdownHookApplication.class, args);
  }

  @PreDestroy
  public void onExit() {
    log.info("###STOPing###");
    try {
      Thread.sleep(5 * 1000);
    } catch (InterruptedException e) {
      log.error("", e);;
    }
    log.info("###STOP FROM THE LIFECYCLE###");
  }
}