我正在尝试Initialize Log4j by Combining Configuration File with Programmatic Configuration

我遵循了手册(尽管它的语法不太正确并且已经过时了),导致出现了以下类:

CustomConfigurationFactory.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;

    }

}

CustomConfiguration.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);

        }

    }
}

现在,在运行此代码并在对Logging API进行任何调用之前调用ConfigurationFactory.setConfigurationFactory(new CustomConfigurationFactory())时,我将获得以下形式的输出到控制台:
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的实现仍然返回有效的配置。

(link to source)

现在,我的第一个想法是在自定义工厂中重写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):

关于java - 自定义ConfigurationFactory结合log4j2中的配置文件,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44227758/

10-10 17:27