Log4J的默认MessageFactory是什么

Mar*_*tin 5 java logging log4j log4j2

文件org.apache.logging.log4j.Logger

   /**
     * Logs a message with parameters at the given level.
     *
     * @param level the logging level
     * @param message the message to log; the format depends on the message factory.
     * @param params parameters to the message.
     * @see #getMessageFactory()
     */
    void log(Level level, String message, Object... params);
Run Code Online (Sandbox Code Playgroud)

但:

  1. 当我设置任何时,使用哪个MessageFactory?
  2. 哪种消息格式使用默认工厂?
  3. 如果默认工厂无法满足我的需求,我该如何设置自己的工厂?

更新:

请在答案中添加类名和XML元素名称.没有正确的搜索条件,很难在谷歌上找到关于Log4J 2.x的任何信息.

Rem*_*pma 12

  1. 如果未设置消息工厂,ParameterizedMessageFactory则默认使用.
  2. 默认情况下,log4j使用消息工厂来进行参数化消息,因此您可以这样做 logger.warn("hello {}", user.getName());
  3. LogManager.getLogger(name, messageFactory)在获得记录器时通过调用来设置自己的工厂.

如果您需要String.format类型的params(System.out.printf格式),您将使用它LogManager.getLogger(MyClass.class, new StringFormatterMessageFactory())来获取记录器.

如果您最常见的用法是参数化消息({}格式),但如果您偶尔希望更多地控制字符串格式化程序提供的输出格式,则可以正常声明您的记录器(因此它使用{}参数化消息),以及使用Logger.printf方法.

例:

class MyClass {
    private static Logger logger = LogManager.getLogger(MyClass.class);

    public void someMethod() {
        // use printf here to precisely control the number of digits displayed
        logger.printf(Level.INFO, "pi: %.5f", Math.PI);
    }
}
Run Code Online (Sandbox Code Playgroud)

这都是代码.不涉及配置(XML或其他).


小智 5

这个线程已经有大约一年的历史了,但也许我仍然可以帮助一些人,因为我刚刚遇到了同样的问题,并找到了一种如何设置自己的默认 MessageFactory 的方法。这有点棘手,也许其他人知道更好的方法,而无需创建那么多类。但对我来说它有效:

  1. 创建您自己的 MessageFactory(从接口扩展AbstractMessageFactory或仅使用MessageFactory接口)
  2. 创建一个新的LoggerContext(从LoggerContext类扩展或使用LoggerContext接口
    • 如果参数是,则覆盖newInstance(LoggerContext, String, MessageFactory)并返回之前定义的 MessageFactorymessageFactorynull
  3. 创建一个新的 ContextSelector(从接口扩展ClassLoaderContextSelector或仅使用ContextSelector接口)。
    • 重写方法 createContext(String, URI) 并返回之前定义的 LoggerContext 的新实例
  4. log4j.component.properties在类路径中创建一个文件,并将属性设置Log4jContextSelector为步骤 3 中创建的 contextSelector 的完全限定名称
    • 替代方案:不创建文件,只需将系统属性设置Log4jContextSelector为 fqn

一些代码示例(没有任何注释):

消息工厂:

public final class OwnMessageFactory extends AbstractMessageFactory
{
  public static final OwnMessageFactory INSTANCE = new OwnMessageFactory();

  @Override
  public Message newMessage(final String message, final Object... params)
  {
    return new OwnDataMessage(message, params);
  }
}
Run Code Online (Sandbox Code Playgroud)

记录器上下文:

public class OwnLoggerContext extends LoggerContext
{
  // constructors

  protected Logger newInstance(final LoggerContext ctx, final String name, MessageFactory messageFactory)
  {
    if (null == messageFactory)
      messageFactory = OwnMessageFactory.INSTANCE;

    return super.newInstance(ctx, name, messageFactory);
  }

}
Run Code Online (Sandbox Code Playgroud)

上下文选择器

public class OwnContextSelector extends ClassLoaderContextSelector
{

  @Override
  protected LoggerContext createContext(String name, URI configLocation)
  {
    return new OwnLoggerContext(name, null, configLocation);
  }

}
Run Code Online (Sandbox Code Playgroud)

log4j2.component.properties

Log4jContextSelector=com.example.OwnContextSelector
Run Code Online (Sandbox Code Playgroud)