我正在寻找在 log4j 可能已初始化或未初始化后配置/重新配置 log4j 的方法。这应该可以独立运行或在 Web 容器中运行。
配置可以由特定任意 URI 处的配置文件来表示。URI 的知识来自应用程序,而不是 log4j 框架。配置也可以通过编程方式完成(问题较少,但问题仍然存在)。
遗憾的是,公共 API 严重缺乏,因此开发人员被迫使用 log4j 核心的实现类编写脆弱的代码。经过数周的研究文档和逐步浏览 log4j 代码,我发现了两种完成重新配置的方法:
类似于以下内容:
((LoggerContext) LogManager.getContext(false)).stop();
Configurator.initialize(buildDefaultConfiguration()); //programmatically building a configuration
Run Code Online (Sandbox Code Playgroud)
或者
((LoggerContext) LogManager.getContext(false)).stop();
Configurator.initialize(null, ConfigurationSource.fromUri(loggingUri)); //passing the configuration source constructed from a known URI
Run Code Online (Sandbox Code Playgroud)
如果当前上下文已经创建并启动(例如在 Web 容器中运行时),两个示例中的第一行都会停止当前上下文。如果 log4j 尚未初始化(例如作为独立应用程序运行时),它将使用默认配置初始化 log4j 并首先启动上下文(作为调用 getContext() 的副作用),然后停止它。
如果当前上下文没有首先停止,则对 Configurator.initialize() 的调用将不起作用。log4j 将忽略您重新初始化的尝试,不会给您任何指示,而只是简单地返回当前上下文。本手册的“使用 ConfigurationBuilder 和配置器重新配置 Log4j”部分中未提及此行为。它只是说:“但是,如果在调用 Configurator.initialize() 之前尝试进行任何日志记录,那么默认配置将用于这些日志事件。” 默认配置还将用于提供的示例中的所有后续日志事件,因为调用 Configurator.initialize() 将不起作用,除非首先停止当前上下文。
类似于以下内容:
((LoggerContext) LogManager.getContext(false)).setConfigLocation(loggingUri);
Run Code Online (Sandbox Code Playgroud)
这以类似的方式工作:如果 log4j 尚未初始化,则对 getContext() 的调用将触发默认上下文的初始化和创建,然后重新配置默认上下文;如果它已经被初始化,那么当前的上下文,无论它是什么,都将被重新配置。配置源将由 log4j 框架从 URI 创建。
不同之处在于,在第一种方式中,上下文被替换,并且旧(已停止)上下文中的所有记录器都将死亡。如果堆栈上的任何代码保存对这些失效记录器的引用并尝试记录它们,那么这将是一个空操作。在第二种方式中,保留上下文,但替换配置,并使用新配置更新现有记录器。 …
log4j2 ×1