如何防止 Spring 应用程序上下文关闭,直到关闭钩子被触发

2023-12-07

我有一个弹簧启动应用程序。

我已经实施了SmartLifecycle我的 bean 中的接口启动了异步 snmp 服务器start方法并将其停止在其中stop method.

一切工作正常,除了主应用程序上下文在启动后立即停止,因此我的服务器 bean 也在启动后立即停止。

我所需要的只是使 spring 上下文仅在关闭钩子被触发时停止。

这不是一个网络应用程序,所以我不需要spring-boot-starter-web,它通过启动 Web 服务器来解决此问题,从而防止上下文停止,直到 Web 服务器停止为止。

我可以使用类似的东西CountDownLatch并等待我的它为零main上下文启动后立即执行的方法。像这样的事情:

public static void main(String[] args) throws InterruptedException {
    ConfigurableApplicationContext ctx = SpringApplication.run(SnmpTrapRetranslatorApplication.class, args);
    CountDownLatch snmpServerCloseLatch = ctx.getBean("snmpServerCloseLatch", CountDownLatch.class);
    snmpServerCloseLatch.await();
}

还有我的服务器 beanstart方法将创建带有计数的锁存器1, while stop方法将调用snmpServerCloseLatch.countDown().

该技术被描述为here.

但这有什么问题是我的main方法负责等待我的自定义服务器 bean 停止。我觉得这是不对的。

举例来说如何spring-boot-starter-web做这个?当启动tomcat时,它会一直运行直到收到关闭钩子,并且不需要在tomcat中有任何管理代码main方法。仅当上下文接收到shoutdown信号时它才会停止。

例如,当我有相同的行为时@Scheduled我的 bean 中的方法。 Spring 也不会自动停止上下文。仅在CTRL-C.

我想达到类似的效果。我的main方法应该只有一行:启动上下文。上下文应该在启动或停止时启动和停止我的异步服务器(已通过SmartLifecycle)并且在请求关闭之前不应停止(CTRL-C、SIGINT 等)。


我的调查使我找到了问题的核心:守护线程.

我使用的 snmp 服务器实现 (snmp4j) 在内部使用守护线程。因此,即使 snmp 服务器启动,JVM 中也不再有活动用户线程,因此它会退出。

TL/DR:

只需将此方法添加到任何 bean(snmp 服务器 bean 是一个很好的选择):

@Scheduled(fixedDelay = 1000 * 60 * 60) // every hour
public void doNothing() {
    // Forces Spring Scheduling managing thread to start
}

(不要忘记添加@EnableScheduling到您的弹簧配置)。

解释:

为了防止在 SNMP 服务器仍在运行时停止 spring 上下文,我们需要any非守护线程在 JVM 中处于活动状态。不必要main线。所以我们可以让main方法来完成。

  1. 我们可以从我们的服务器 bean 运行新的非守护线程start方法。该线程将wait一些锁定while循环检查一些running变量,而我们的stop方法将设置这个running变量为false and notifyAll在这把锁上。

    这样,我们的非守护线程将一直处于活动状态,直到触发 Shotdown 挂钩(并阻止 JVM 退出)。 shutdown hook之后,spring上下文生命周期close方法将调用所有SmartLifecycle bean's close方法,这将导致 SNMP 服务器 beanstop方法调用,这将导致设置running设置为 false,这将导致我们的非守护线程停止,从而允许 JVM 正常停止。

  2. 或者我们可以以类似的方式使用 Spring 的调度线程。它也是非守护线程,因此会阻止 JVM 退出。 Spring 自己管理这个线程,所以当 shutdown hook 被触发时,它会自动停止它。

    为了让 Spring 的调度线程启动,我们需要任何@Scheduled任何 bean 中的方法。


我认为第一种(手动)方法仍然更“正确”,但需要更多的异步编码(众所周知,这很容易出错)。谁知道Spring将来会如何改变它的调度实现。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 Spring 应用程序上下文关闭,直到关闭钩子被触发 的相关文章

随机推荐

  • 文件修订可疑行为?

    今天似乎出现了 GoogleDrive 非本机文件修订版的新问题 几个月来 我们已经通过 Google Drive API 从 C 应用程序成功更新了 Google Drive 帐户中的现有文档 有些文件有 40 60 甚至超过 100 个
  • 如何通过用户id显示数据库中的记录

    我想按用户 ID 显示数据库中的记录 这意味着员工必须输入员工ID和密码并提出新项目的请求 并且该请求将被保存在数据库中 该请求工作正常 但在 request php 页面之后 我想在receipt php 中显示该员工订购的商品 我怎么能
  • IBM Watson - 对话 API 集成返回“未找到资源”错误 (404)

    我正在尝试集成来自 salesforce 的 Watson Http Callout 并收到 404 错误 然后我尝试使用 Postman 工具进行相同的操作 但得到相同的结果 在请求标头中添加了对话凭据 请求端点 https gatewa
  • Python:Selenium xpath 查找具有不区分大小写字符的元素?

    我有能力做到这一点 search View List driver find elements by xpath text normalize space s parent search 但我需要它忽略并将所有元素与文本匹配 例如 VieW
  • iOS Core Plot CPTAxisLabel 与 CTPlot 对齐

    请看下面这张图片 我已附上文件 我的问题是CPTAxisLabel标签 它们被放置在勾号下方 但不被放置在CPTPlot如我所愿 如何向该标签添加左偏移量 我需要将我的标签放置在中间CPTPlot object 更新 void config
  • 如何编写中间带有参数的 PowerShell 别名?

    我正在尝试设置 Windows PowerShell 别名来使用某些参数运行 MinGW 的 g 可执行文件 但是 这些参数需要位于文件名和其他参数之后 我不想经历尝试设置函数之类的麻烦 有没有一种方法可以简单地说 alias mybuil
  • 如何使两种不兼容的类型,但具有相同的成员,可以互换?

    昨天 我们团队中的两个人来找我 提出了一个不常见的问题 我们正在我们的 winforms 应用程序之一中使用第三方组件 所有代码都已经针对它编写了 然后 他们希望将同一供应商提供的另一个第三方组件合并到我们的应用程序中 令他们高兴的是 他们
  • swift tableview如何选择所有行

    我在表格视图中有按钮 我想当我按下该按钮时将选择所有单元格行 该怎么做 我尝试了很多但一无所获 我很困惑如何让按钮接触细胞 我试图让 var 像这样 var x false 那我确实喜欢 if x true Code 当你按下按钮时它就会是
  • 使用 Python 解析文件中的嵌套循环

    目前Python读取文件的每一行并执行一个函数doStep 该函数将传递正在读取的行上的任何内容 data txt a b c b read py fin open data txt for step in fin doStep step
  • Android Wear:收听传入通知

    是否可以在可穿戴 Android 应用程序中监听传入通知 我尝试过实施一个通知监听服务 但是服务的onNotificationPosted 从未被称为 public class MyListenerService extends Notif
  • 如何将应用提交到应用商店?

    我最近制作了我的第一个 iPhone 应用程序 我对 iPhone 编程完全陌生 如何将应用提交到应用商店 因为我是菜鸟 所以我会得到一些详细解释的更好帮助 您可以在中找到详细的解释iOS 开发者计划用户指南
  • 使用 Writer 将 int 写入文本文件

    Writer wr new FileWriter 123 txt wr write 123 wr close 输出文件包含 哪里有问题 怎么写int到文本文件使用Writer 你必须写字符串 你可以试试 wr write 123 OR wr
  • 从 PHP 5.3 开始,mssql_connect 不再工作

    我刚刚收到我们主机的一封电子邮件 他们已将 PHP 升级到 5 3 但不幸的是 所有脚本现在都已损坏 我追踪到了这个函数mssql 连接失败 支持人员告诉我 这在 5 3 中已被弃用 这怎么可能是真的 现在如何在 PHP 5 3 下连接到
  • 如何解决GCC中的包含文件名冲突?

    我有两个名为string h在不同的库中 它们相互冲突 甚至与标准C包含文件的同名冲突 无需使用任何string h除了标准的 但我需要在 GCC 搜索路径中包含库头路径 目前我使用类似的东西 I usr local include lib
  • 如何调试 dsymutil 错误:“Clang 模块预计只有 1 个编译单元。”

    在 iOS 应用程序的GenerateDSYMFile 阶段收到此错误消息 Users name Library Developer Xcode DerivedData ModuleCache HASH FrameworkName HASH
  • EOFException - 如何处理?

    我是一名初学者 Java 程序员 遵循java教程 我正在使用一个简单的 Java 程序Java教程 s 数据流页面 并且在运行时 它不断显示EOFException 我想知道这是否正常 因为读者最终必须到达文件的末尾 import jav
  • HMVC codeigniter 适用于本地服务器,但不适用于 Web 服务器

    这真是要了我的命 我有什么 CI版本 2 1 4 模块化扩展 HMVC 作者 wiredesignz 一个基本的 codeigniter hmvc 项目 可以与 php 5 5 3 的本地服务器 mamp 中的设置配合良好 我的问题 在我将
  • 如何获取默认的 Cargo 输出目录以匹配目标架构?

    我希望构建输出目录遵循我正在构建的架构 目前 当我在没有任何目标的情况下使用 Cargo build 时 它将输出放入 target debug 或 target release 中 当我为其他目标架构构建时 它将它们放入 target a
  • android - 文本输入类型人名不起作用

    在我的 android 项目中 我想要一个类型为 personname 的文本字段 默认情况下大写锁定处于激活状态 但是 此代码不起作用
  • 如何防止 Spring 应用程序上下文关闭,直到关闭钩子被触发

    我有一个弹簧启动应用程序 我已经实施了SmartLifecycle我的 bean 中的接口启动了异步 snmp 服务器start方法并将其停止在其中stop method 一切工作正常 除了主应用程序上下文在启动后立即停止 因此我的服务器