Wat*_*ter 5 java logging spring
我正在使用 Spring,并且在终止时我让 @PreDestroy 清理 bean。我不明白为什么随机记录有时会成功,而在其他情况下会失败。
// Using Log4j2
Logger log = LogManager.getLogger(MyClass.class);
@PreDestroy
public void close() {
log.warn("Test");
}
Run Code Online (Sandbox Code Playgroud)
有时我什么也得不到(没有记录“测试”),有时我会得到:
[13:48:44] INFO MyClass: Test
Run Code Online (Sandbox Code Playgroud)
如果我包含System.out.println("Is this run?");在 close() 方法中,它将始终打印。
我实际上不确定发生了什么。我不知道是不是因为 JVM 正在关闭并且记录器被杀死......但我认为这会引发某种异常?
请注意,日志记录同时记录到文件 + 标准输出中,我不知道这是否会影响任何事情。日志记录适用于其他无数的数千行代码,但不是这个。
注意:如果它最终成为这个特定的库,我愿意切换日志库。
编辑: MyClass 将是 spring.xml 文档中的一个 bean。
我认为这归结为Runtime.addShutdownHook:
当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。
所以,只要 LogManager 和 Spring IOC 容器都被 JVM 关闭钩子关闭,就没有办法确保消息会被记录下来。如果先关闭 LogManager,消息就会丢失。如果首先关闭 IOC 容器,则会记录该消息。
如果您在 JEE 容器中运行,则可能无法更改此设置。
但是,如果您在独立环境中运行,则可以将 a 添加shutdownHook="disable"到 Log4j 2<configuration>标记。这可以防止 Log4j 2 注册它自己的关闭钩子。然后,不是调用ctx.registerShutdownHook()(推荐的关闭 IOC 的方法),而是注册自己的关闭钩子。就像是:
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);
Run Code Online (Sandbox Code Playgroud)
更新:更正了关闭 Log4j2 的过程。
警告:我远离我常用的构建机器,所以我没有编译它,但我相信它正在击中正确的 API。
| 归档时间: |
|
| 查看次数: |
1782 次 |
| 最近记录: |