我正在尝试 Initialize Log4j by Combining Configuration File with Programmatic Configuration .
我遵循了手册(尽管它的语法不太正确而且已经过时),导致了以下类:
自定义配置工厂.java:
package factory;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationFactory;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.Order;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import java.net.URI;
@Plugin(name = "CustomConfigurationFactory", category = ConfigurationFactory.CATEGORY)
@Order(1)
public class CustomConfigurationFactory extends ConfigurationFactory {
/**
* Valid file extensions for XML files.
*/
private static final String[] SUFFIXES = new String[]{".xml", "*"};
/**
* Return the Configuration.
*
* @param source The InputSource.
* @return The Configuration.
*/
public Configuration getConfiguration(LoggerContext context, ConfigurationSource source) {
return new CustomConfiguration(context, source);
}
/**
* Returns the file suffixes for XML files.
* @return An array of File extensions.
*/
public String[] getSupportedTypes() {
return SUFFIXES;
}
}
自定义配置.java:
package factory;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.ConfigurationSource;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.apache.logging.log4j.core.config.xml.XmlConfiguration;
import java.util.Map;
public class CustomConfiguration extends XmlConfiguration {
CustomConfiguration(LoggerContext context, ConfigurationSource configSource) {
super(context, configSource);
}
@Override
protected void doConfigure() {
super.doConfigure();
final LoggerConfig rootLogger = getRootLogger();
final Map<String, Appender> appenderMap = rootLogger.getAppenders();
if (MainClass.DEBUG) {
rootLogger.addAppender(appenderMap.get("Console"), Level.ALL, null);
} else {
rootLogger.addAppender(appenderMap.get("Mail"), Level.ERROR, null);
}
}
}
现在,在运行它并调用 ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory())
之前调用 Logging API 时,我会以
ERROR StatusLogger Reconfiguration failed: No configuration found for 'someNumbersAndChars' at 'null' in 'null'
调试时,我发现这是在我第一次获取 Logger
时打印的。原因是,如果提供自定义 ConfigurationFactory
,ConfigurationFactory.getConfiguration(LoggerContext, String, URI)
的实现由 ConfigurationFactory
的私有(private)子类 Factory
(默认工厂)将被 ConfigurationFactory
的实现覆盖。
如果 URI 是这样的话,ConfigurationFactory
的实现简单地返回 null
,而 ConfigurationFactory.Factory
的实现仍然返回一个有效的配置.
我现在的第一个想法是在我的自定义工厂中覆盖 ConfigurationFactory.getConfiguration()
的这些重载,但必须有另一种方法,对吗? ;)
最佳答案
我通过调用解决了这个问题
System.setProperty("log4j.configurationFactory", CustomConfigurationFactory.class.getName());
作为替代方法,使用此 JVM 启动参数:
-Dlog4j.configurationFactory=factory.CustomConfigurationFactory
代替
ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory());
在第一次访问 LogManager
之前。
-
编辑:您还可以在文件 log4j2.component.properties
中配置此设置。
内容:
log4j.configurationFactory=factory.CustomConfigurationFactory
通过这样做,您可以确保在加载任何记录器类之前应用此设置,并避免类初始化顺序的潜在问题。
如果您在 Log4j2 源代码中查找 org.apache.logging.log4j.util.PropertiesUtil
的用法,您可以找到可以通过这种方式配置的所有设置。
-
在分析/调试问题时,我注意到我的 ConfigurationFactory
已创建,但未用于获取配置。
最后我在docs中找到了这段话,这解释了一切(我们可能没有足够早地调用 setConfigurationFactory
):
During initialization, Log4j 2 will search for available ConfigurationFactories and then select the one to use. The selected ConfigurationFactory creates the Configuration that Log4j will use. Here is how Log4j finds the available ConfigurationFactories:
- A system property named "log4j.configurationFactory" can be set with the name of the ConfigurationFactory to be used.
- ConfigurationFactory.setConfigurationFactory(ConfigurationFactory) can be called with the instance of the ConfigurationFactory to be used. This must be called before any other calls to Log4j.
- A ConfigurationFactory implementation can be added to the classpath and configured as a plugin in the "ConfigurationFactory" category. The Order annotation can be used to specify the relative priority when multiple applicable ConfigurationFactories are found.
关于java - 自定义ConfigurationFactory结合log4j2中的配置文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44227758/