gpt4 book ai didi

java - Spring 的 @PreDestroy 导致随机记录而不是记录

转载 作者:搜寻专家 更新时间:2023-11-01 02:23:59 27 4
gpt4 key购买 nike

我正在使用 Spring,并在终止时让 @PreDestroy 清理 bean。我不明白为什么随机登录有时会成功,而其他人会失败。

// Using Log4j2
Logger log = LogManager.getLogger(MyClass.class);

@PreDestroy
public void close() {
log.warn("Test");
}

有时我什么也得不到(没有记录“测试”),其他时候我会得到:

[13:48:44] INFO  MyClass: Test

如果我在 close() 方法中包含 System.out.println("Is this run?");,它将始终打印。

我实际上不确定发生了什么。我不知道是不是因为 JVM 正在关闭并且记录器被杀死...但我认为这会引发某种异常?

请注意,日志记录同时记录到文件和标准输出,我不知道这是否会影响任何事情。日志记录适用于其他无数行代码,但不适用于此。

注意:如果最终成为这个特定的库,我愿意切换日志库。

编辑:MyClass 将是 spring.xml 文档中的一个 bean。

最佳答案

我认为归结于此,来自 Runtime.addShutdownHook :

When the virtual machine begins its shutdown sequence it will start all registered shutdown hooks in some unspecified order and let them run concurrently.

因此,只要 LogManager 和 Spring IOC 容器都被 JVM 关闭 Hook 关闭,就无法确保消息会被记录下来。如果先关闭 LogManager,消息就会丢失。如果 IOC 容器先关闭,则记录消息。

如果您在 JEE 容器中运行,您可能无法改变这一点。

但是,如果您在独立环境中运行,您可以添加 shutdownHook="disable"到 Log4j 2 <configuration>标签。这会阻止 Log4j 2 注册它自己的关闭 Hook 。然后,而不是调用 ctx.registerShutdownHook() (关闭 IOC 的推荐方法),您注册自己的关闭 Hook 。像这样的东西:

class MyShutdownHook extends Thread {
private AbstractApplicationContext ctx;
public MyShutdownHook(AbstractApplicationContext ctx) {
this.ctx = ctx;
}
public void run() {
ctx.close();
Set<LoggerContext> contexts = new HashSet<>();
for (Logger logger : LoggerContext.getLoggers()) {
contexts.add(logger.getContext());
}
for (LoggerContext ctx : contexts) {
Configurator.shutdown(LogManager.getContext());
}
}
}

AbstractApplicationContext ctx = /* create context */
Runtime.getRunTime().addShutdownHook(new MyShutdownHook(ctx);

更新:更正了关闭 Log4j2 的过程。
警告:我远离我常用的构建机器,所以我没有编译这个,但我相信它会使用正确的 API。

关于java - Spring 的 @PreDestroy 导致随机记录而不是记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30426533/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com