java 运行 SpringBootApplication PostConstruct 和 PreDestroy

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42779431/
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-11-03 06:52:14  来源:igfitidea点击:

Running SpringBootApplication PostConstruct and PreDestroy

javaspringdockerspring-bootsigkill

提问by sapwood

I have troubles with running spring application in docker container (both spring and docker have latest versions in my environment). I want to have healthy life cycle for application class AnalysisServiceBootstrap: to run initialization code with method start() right AFTER creation of AnalysisServiceBootstrap and also to run method stop() right BEFORE destruction of AnalysisServiceBootstrap (I want to run stop() code when someone stops the application).

我在 docker 容器中运行 spring 应用程序时遇到了麻烦(spring 和 docker 在我的环境中都有最新版本)。我希望应用程序类 AnalysisServiceBootstrap 拥有健康的生命周期:在创建 AnalysisServiceBootstrap 之后立即使用方法 start() 运行初始化代码,并在销毁 AnalysisServiceBootstrap 之前正确运行方法 stop()(我想在有人时运行 stop() 代码停止应用程序)。

I have following code:

我有以下代码:

package com.pack;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class AnalysisServiceBootstrap {

    // called OK on docker "start <containerId>"
    @PostConstruct
    public void start() throws Exception {
        // some init code
    }

    // NOT called on "docker stop <containerId>"
    @PreDestroy
    public void stop() {
       // some destroy code
    }

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

For some reason I can not get method stop() running on docker stop. I tried several ways offered on stackoverflow and other resources, but all of them did not work for me.

出于某种原因,我无法在 docker stop 上运行 stop() 方法。我尝试了 stackoverflow 和其他资源上提供的几种方法,但所有这些方法都不适合我。

I will be glad to have code that works for you (not just some vogue suggestions).

我很高兴有适合您的代码(不仅仅是一些时尚建议)。

Here is almost exact docker file of mine:

这里几乎是我的 docker 文件:

FROM *********:6556/service-jvm

ARG SERVICE_JAR_FILE

ENV SERVICE_NAME service
ENV HTTP_PORT 603
ENV HTTPS_PORT 604
ENV SERVICE_JAR /opt/my/project/${SERVICE_JAR_FILE}
EXPOSE ${HTTP_PORT} ${HTTPS_PORT}
COPY ${SERVICE_JAR_FILE} /opt/my/project/${SERVICE_JAR_FILE}

CMD java -Xms1024m -Xmx1024m -dump:"/opt/my/project/dumppath" -javaagent:/opt/my/project/agent.jar -Djav.awt.headless=true -jar ${SERVICE_JAR} 

But you are invited to post here any working docker file that you have.

但是我们邀请您在此处发布您拥有的任何可用的 docker 文件。

Thanks a lot.

非常感谢。

回答by Andrii Abramov

From the documentation:

从文档:

docker stop

Stop one or more running containers The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL

码头站

停止一个或多个正在运行的容器 容器内的主进程会收到SIGTERM,并在一个宽限期后,SIGKILL

By executing docker stopyou are just killing the java (Spring) process.

通过执行,docker stop您只是在杀死 java (Spring) 进程。

So what are the guarantees that Spring context will shutdown properly?

那么,Spring 上下文将正确关闭的保证是什么?

The right way to handle SIGTERMin Spring applications is to add shutdown hook.

SIGTERM在 Spring 应用程序中处理的正确方法是添加关闭钩子。

The final code should look like this:

最终代码应如下所示:

package com.pack;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.web.SpringBootServletInitializer;

@SpringBootApplication
public class AnalysisServiceBootstrap {

    @PostConstruct
    public void start() throws Exception {
        // some init code
    }

    @PreDestroy
    public void tearDown() {
       // some destroy code
    }

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                // write here any instructions that should be executed
                tearDown();
            }   
        });


        SpringApplication.run(AnalysisServiceBootstrap.class, args);
    }
}

The process is described in the following questions:

该过程在以下问题中描述:

回答by Barath

Register a shutdown hook to the application as mentioned here Spring Boot shutdown hook

将关闭挂钩注册到应用程序,如此处所述 Spring Boot 关闭挂钩

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.

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