美文网首页
log4j2使用手册(中文)第六章 使用

log4j2使用手册(中文)第六章 使用

作者: 在下喵星人 | 来源:发表于2019-07-21 15:54 被阅读0次

    静态Logger VS 非静态Logger

    与Java中的任何变量一样,Logger可以声明为静态变量或类成员变量。 但是,在选择将Logger指定为静态和非静态时,需要考虑几个因素。 通常,最好将Loggers声明为静态。

    1. 使用默认的ContextSelector,ClassLoaderContextSelector时,实例化新的Logger是一项相当昂贵的操作。创建Logger时,ClassLoaderContextSelector将找到与Logger关联的ClassLoader,并将Logger添加到与该ClassLoader关联的LoggerContext。
    2. 创建Logger后,除非删除与其关联的LoggerContext,否则不会删除Logger。 通常,删除Logger只会在应用程序关闭或取消部署时发生。 每次使用相同的Logger名称调用getLogger都将返回相同的Logger实例。 因此,静态或非静态Logger之间的差异非常小。
    3. 静态和非静态Logger之间没有行为差异。 两者都将在创建时分配Logger名称,这通常是与其关联的类的名称。 有关更多信息,请参阅下面有关Logger名称与类名称讨论。

    Logger名称VS类名称

    创建Logger时需要指定Logger名称。 调用日志方法时,日志事件中的类名值将反映调用日志方法的类的名称,该名称不一定与创建Logger的类相同。 以下示例说明了这一点。

    父类创建一个静态Logger和并将静态变量值付给一个成员变量。 它有一个执行日志记录的方法,但提供对两个Logger的访问,一个是静态的,一个可以被覆盖。

    package org.apache.logging;
    
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      import org.apache.logging.log4j.Marker;
    
      /**
      *
      */
      public abstract class Parent {
    
          // The name of this Logger will be "org.apache.logging.Parent"
          protected static final Logger parentLogger = LogManager.getLogger();
    
          private Logger logger = parentLogger;
    
          protected Logger getLogger() {
              return logger;
          }
    
          protected void setLogger(Logger logger) {
              this.logger = logger;
          }
    
    
          public void log(Marker marker) {
              logger.debug(marker,"Parent log message");
          }
      }
    

    Child类继承一个父类。 它提供了自己的记录器并且有三个日志记录的方法,一个使用此类中的logger,一个使用父类中的静态logger,另一个logger可以设置为父类或子类的logger。

    package org.apache.logging;
    
      import org.apache.logging.log4j.LogManager;
      import org.apache.logging.log4j.Logger;
      import org.apache.logging.log4j.Marker;
    
      /**
      *
      */
      public class Child extends Parent {
    
          // The name of this Logge will be "org.apache.logging.Child"
          public Logger childLogger = LogManager.getLogger();
    
          public void childLog(Marker marker) {
              childLogger.debug(marker,"Child logger message");
          }
    
          public void logFromChild(Marker marker) {
              getLogger().debug(marker,"Log message from Child");
          }
    
          public void parentLog(Marker marker) {
              parentLogger.debug(marker,"Parent logger, message from Child");
          }
      }
    

    该应用程序执行四次日志记录方法。 child.log和child.logFromChild前两次日志输出使用的是父类中静态Logger。 child.log和child.logFromChild后两次输出设置为使用子类中的Logger。 在每个方法的第一次和第三次调用中,传递空标记。 在第二个和第四个中,传递了一个名为“CLASS”的标记。

    package org.apache.logging;
    
      import org.apache.logging.log4j.Marker;
      import org.apache.logging.log4j.MarkerManager;
    
      public class App {
    
          public static void main( String[] args ) {
              Marker marker = MarkerManager.getMarker("CLASS");
              Child child = new Child();
    
              System.out.println("------- Parent Logger ----------");
              child.log(null);
              child.log(marker);
              child.logFromChild(null);
              child.logFromChild(marker);
              child.parentLog(null);
              child.parentLog(marker);
    
              child.setLogger(child.childLogger);
    
              System.out.println("------- Parent Logger set to Child Logger ----------");
              child.log(null);
              child.log(marker);
              child.logFromChild(null);
              child.logFromChild(marker);
          }
      }
    

    下面配置利用log4j根据日志事件的属性选择模式的能力。在这种情况下,类名模式%C在CLASS标记存在时使用类名称,而%c在CLASS标记不存在时使用Logger名称。

    <?xml version="1.0" encoding="UTF-8"?>
    <Configuration status="error">
      <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
          <PatternLayout>
            <MarkerPatternSelector defaultPattern="%sn. %msg: Logger=%logger%n">
              <PatternMatch key="CLASS" pattern="%sn. %msg: Class=%class%n"/>
            </MarkerPatternSelector>
          </PatternLayout>
        </Console>
      </Appenders>
      <Loggers>
        <Root level="TRACE">
          <AppenderRef ref="Console" />
        </Root>
      </Loggers>
    </Configuration>
    

    下面的输出说明了使用Logger名称和类名称之间的区别。 所有奇数项都打印记Logger名称(%c),而所有偶数项打印调用记录方法的类的名称(%C)。 以下列表中结果输出显示数字与描述相匹配。

    1. 使用父类静态Logger在执行日志记录。 记录器名称与父类的名称匹配。
    2. 使用具有类名称模式下使用父类的静态记录器行日志记录。 虽然该方法是针对Child实例调用的,但它是在Parent中实现的,所以会输出父类名称。
    3. 使用父类中的Logger在Child中执行日志记录,因此父类的名称将打印为Logger名称。
    4. 使用父类中的日志程序在子类中执行日志记录。由于调用日志记录方法的方法位于子类中,因此出现子类名。
    5. 使用父类中的静态Logger在Child中执行日志记录,因此父类的名称将打印为Logger名称。
    6. 使用父类中的静态Logger在Child中执行日志记录。 由于调用日志记录方法的方法在Child中,因为子类名打印为Logger名称。
    7. 使用Child的Logger执行父类的日志记录方法。 记录器名称与子名称匹配,因此将打印子类名称。
    8. 使用Child的Logger执行父类中日志记录方法。 虽然该方法是针对Child实例调用的,但它是在Parent中实现的,因使用Child的Logge执行此它显示父类类名。
    9. 使用Child的Logger执行Child中日志记录方法,因此子类的名称将作为Logger名称打印。
    10. 使用Child的Logger执行Child中日志记录方法。 由于调用日志记录的方法在Child中,因为它是出现的子类类名。
    ------- Parent Logger ----------
      1. Parent log message: Logger=org.apache.logging.Parent
      2. Parent log message: Class=org.apache.logging.Parent
      3. Log message from Child: Logger=org.apache.logging.Parent
      4. Log message from Child: Class=org.apache.logging.Child
      5. Parent logger, message from Child: Logger=org.apache.logging.Parent
      6. Parent logger, message from Child: Class=org.apache.logging.Child
      ------- Parent Logger set to Child Logger ----------
      7. Parent log message: Logger=org.apache.logging.Child
      8. Parent log message: Class=org.apache.logging.Parent
      9. Log message from Child: Logger=org.apache.logging.Child
      10. Log message from Child: Class=org.apache.logging.Child
    

    在上面的示例中,声明了两个Logger。 一个是静态的,一个是非静态的。 在查看结果时,无论是否如何声明记录器,结果都将完全相同。 记录器的名称始终来自创建它的类,每个日志事件中的类名将始终反映从中调用日志记录方法的类。

    应该注意,打印位置信息(类名,方法名和行号)会有很大的性能损失。 如果方法名称和行号不重要,通常最好确保每个类都有自己的Logger,以便记录器名称准确反映执行日志记录的类。

    相关文章

      网友评论

          本文标题:log4j2使用手册(中文)第六章 使用

          本文链接:https://www.haomeiwen.com/subject/iezjlctx.html