当前位置: 首页 > 知识库问答 >
问题:

Spring Boot 2.1和Java 11中的Bean生命周期

施雅懿
2023-03-14

我的项目正在从使用Java 8的Spring Boot 2.0.4迁移到使用Java 11的Spring Boot 2.1.0。当应用程序使用Spring Boot 2.0.4和Java 8构建并在Docker/Docker Compose中运行时,调用了@PostConstruct-带注释的方法,但在迁移到Spring Boot 2.1.0和Java 11之后,不再调用@PreDestroy-带注释的方法。

我尝试过从注释切换到实现initializebeanDisposableBean,如下所述,但是DisposableBean。不调用destroy方法。

我还尝试向javax.annotation版本1.3.2添加依赖项,结果相同。

如何复制:

使用生命周期bean创建一个最小的Spring应用程序:

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class Life implements InitializingBean, DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("--- Life.shutdown");
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("--- Life.startup");
    }
}

从目标子文件夹启动Spring应用程序:

cd target
java -jar demo-0.0.1-SNAPSHOT.jar

当应用程序使用Ctrl C停止时,DisposableBean。毁灭叫做毁灭。

返回到父文件夹:

cd ..

使用Maven启动Spring应用程序:

mvn spring-boot:run

当应用程序使用Ctrl C停止时,DisposableBean。毁灭叫做毁灭。

Dockerfile:

FROM openjdk:11.0.1-jre-slim
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT java -jar /app.jar

生成、运行和停止Docker映像:

docker build -t demo .
docker run -p 8080:8080 demo
docker ps
docker stats 3ca5b804ab13
docker stop 3ca5b804ab13
docker logs 3ca5b804ab13

当应用程序使用docker stop停止时,DisposableBean。毁灭不叫毁灭。

docker撰写。yml:

demo:
  image: demo
  ports:
  - '8080:8080'

使用Docker Compose运行Docker image(模拟OpenShift):

docker-compose up
docker-compose down
demo_demo_1 exited with code 137

当应用程序停止使用docker compose down时,DisposableBean。毁灭不叫毁灭。

我怀疑Docker在发出SIGKill之前正在尝试SIGTERM,因为在容器被杀死之前有10秒的延迟。

共有2个答案

端木权
2023-03-14

我想我找到了解决方案(在这篇博客文章中):在Docker文件中使用exec表单而不是shell表单,这样Docker发出的SIGTERM会命中java进程,而不是bash进程(它不会将信号转发给任何子进程)。

  • Shell表单(使用/bin/sh-cshell执行):ENTRYPOINT java-jar/app。jar
骆鸿运
2023-03-14

在很多地方,设置可能会出错。首先,我建议确定java/spring部件是否存在一些问题,还是与docker/environment相关的问题。从这个问题来看,它听起来与java有关,但实际上我怀疑它不在java/spring中。

因此,mvn spring boot:run按预期工作,我看到您将spring boot应用程序打包为jar(app.jar),很可能带有spring boot插件。这也是一个可能出错的地方,因为spring boot使用一个特殊的类加载器在运行时加载内容。

因此,为了完全消除java/Spring部分,请导航到您的目标目录并运行java-jarapp.jar(当然,请确保java 11安装在您的本地机器上)。如果它不起作用-调查java /spring部分,否则继续使用docker部分。

应用程序很可能会按预期工作。

现在,关于docker的设置。在运行docker comush并看到它失败后,

可以使用以下命令:

docker ps -a // -a flag to see container ids of containers that were stopped for whatever reason as well.

现在找到退出的java进程的id并检查其日志:

docker logs <ID_OF_THE_EXTED_CONTAINER_GOES_HERE> 

现在,应用程序上下文很可能无法启动(可能是网络相关的问题或其他问题,在这里,如果看不到实际的日志,很难判断),因此出现了问题。

另一个可能的问题是应用程序“太重”(我的意思是它超过了docker容器上的一些配额)。

你可以运行docker统计

 类似资料:
  • 视图和bean一直在工作,直到我试图修复非标准名称,现在我已经打破了两者之间的连接。奇怪的是,“返回”按钮有正确的链接,但内容就是不显示,也不记录。为什么不执行Detail.get注释()? 我一直在浏览焊接文档,并试图更好地理解@Inject。似乎有一个我也不明白的生命周期问题。如果它不是生命周期,那么我甚至不能推测为什么Detail.get注释()从未在glassfish日志中显示: 值200

  • 本文向大家介绍spring中bean的生命周期详解,包括了spring中bean的生命周期详解的使用技巧和注意事项,需要的朋友参考一下 1.Spring IOC容器可以管理bean的生命周期,Spring允许在bean生命周期内特定的时间点执行指定的任务。 2.Spring IOC容器对bean的生命周期进行管理的过程: ① 通过构造器或工厂方法创建bean实例 ② 为bean的属性设置值和对其他

  • 我使用CDI注释定义了一个RequestScoped bean,如下所示。我有几个页面使用同一个bean。当我从一页导航到另一页时。bean obj保持不变。即使我更改了会话(使用不同的用户登录)。bean对象没有改变。 根据RequestScope定义,bean实例应该为每个新请求重新创建。我错过了什么? 我正在使用JSF/Primefaces。从create输入的值。导航到详细信息后可以看到x

  • 首先简单说一下(以下为一个回答的参考模板) 1、实例化一个Bean--也就是我们常说的new; 2、按照Spring上下文对实例化的Bean进行配置--也就是IOC注入; 3、如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)方法,此处传递的就是Spring配置文件中Bean的id值 4、如果这个Bean已经实现了BeanFactoryA

  • 我对Spring的生命周期感到困惑。 上面的代码片段是否创建了对象? 如果上述答案为真。 a) 然后,对于作用域为“singleton”的bean,获取在上述代码片段中创建的对象。我是对还是错? b)对于范围为“原型”的情况,创建的对象是否未使用。因为,容器总是返回新对象。 上面的代码片段是否创建了对象? 如果答案是假的, Spring框架如何验证bean定义是否正确。 根据亨利的回答 通常,单例

  • 本文向大家介绍浅谈Spring中Bean的作用域、生命周期,包括了浅谈Spring中Bean的作用域、生命周期的使用技巧和注意事项,需要的朋友参考一下 本文主要探究的是关于Bean的作用域、生命周期的相关内容,具体如下。 Bean的作用域   Spring 3中为Bean定义了5中作用域,分别为singleton(单例)、prototype(原型)、request、session和global s