如果没有在 Web 应用程序中运行,那么关闭 Log4j2 的正确方法是什么?我只看到一个 noop LogManager.shutdown()
3 回答
对此没有公共 API,但您可以使用
((LifeCycle) LogManager.getContext()).stop();
如果您有兴趣为此提供公共 API,请在此处投票或添加评论:https ://issues.apache.org/jira/browse/LOG4J2-124
更新:
在 Log4j 2.5 中,您可以调用Configurator.shutdown()
. 使用 Log4j 2.6,您可以调用LogManager.shutdown()
.
解释和背后的故事
Log4j 2 在内部使用的是他们所说的ShutdownRegistrationStrategy。它由一个类组成,该类注册一个或多个将在适当时间调用的关闭回调。它们提供名为的接口ShutdownCallbackRegistry
和它们的默认实现名为DefaultShutdownCallbackRegistry
. 此实现将自己注册为 JVM 的关闭挂钩,使用Runtime.getRuntime().addShutdownHook()
.
根据 Log4j 2 错误跟踪器(LOG4J2-868和LOG4J2-658)上的一些问题,正确的方法是提供您自己的ShutdownCallbackRegistry
接口实现。由于没有关闭 Log4j 2 的公共 API,因此这是存档此文件的唯一真实有效的方法。
建议的解决方案
所以,为了解决这个问题,我实现了我自己的ShutdownCallbackRegistry
接口版本。它主要做与默认实现相同的事情,但不是将自己注册为关闭钩子,而是等到它被手动调用。通过将对象的实例保存在静态字段中,这可以在内部实现。然后,您只需调用单个静态方法即可启动关闭过程,因此我将其命名为StaticShutdownCallbackRegistry
.
您可以在GitHub/DjDCH/Log4j-StaticShutdown上找到完整的解决方案和说明,并在您自己的项目中使用它。基本上,最后,你只需要在你的应用程序中做这样的事情:
StaticShutdownCallbackRegistry.invoke();
我不能毫无疑问地说这是完美的解决方案并且我的实现是完美的,但我试图以正确的方式做到这一点(根据不存在的关于它的文档)。我很高兴听到您的反馈,无论您是否认为此解决方案合适。
Log4j-Web库是在 Web 应用程序中正确清理资源的首选方式。
要启用它,请将这样的依赖项添加到您的 pom.xml
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-web</artifactId>
<version>${log4j2.version}</version>
<scope>runtime</scope>
</dependency>
它将在 Servlet 3.* 环境中“开箱即用”地工作。如果您使用的是较旧的 Servlet 规范,请在此处获得如何为 log4j2 启用正确清理的详细信息: https ://logging.apache.org/log4j/2.x/manual/webapp.html