Contents
  1. 1. Logger的理解
  2. 2. 继承关系
    1. 2.1. 父类
    2. 2.2. 用户自定义的Logger
    3. 2.3. 代码中直接定义子类
  3. 3. 继承关系的用处
  4. 4. RootLogger
  5. 5. 类实例Logger

Java代码中可以通过继承关系来扩展类的功能,在Log4J也有类似的机制。

Logger的理解

在log4j的使用中,我们是使用Logger.getLogger(name)来获取Logger实例,这里的Logger实例中的名字是有name来指定,这个那么就限定了我们这个logger会使用什么配置。个人的理解是,在log4j中的Logger的实例是根据名字来唯一存在的,一个名字只会存在一个Logger实例。大概可以这样理解,每一个getLogger返回的都是Logger的一个子类,这个子类是静态,每个子类之间是根据名字来区分的。

继承关系

父类

既然是继承,那么需要一个父类,Logger是不能直接实例化,而我们可以通过Logger.getRootLogger()方式来取一个名字标识为rootLogger的Logger子类,这个类我们可以看做其他Logger子类的父类,所有的Logger子类都会继承自它。

用户自定义的Logger

用户自定义的Logger其实际意义就是指定Log4J生成一个指定名称和配置的子类。
比如在log4j.properties文件中定义了这么一句

log4j.logger.father=DEBUG, fatherConfig

那么这句话的意思是说定义一个名字为father的logger类,在代码中可以通过Logger.getLogger(“father”); 来获取这个father对应Logger类。那如果我们需要定义一个这个father的子类就应该:

log4j.logger.father.children=INFO,childrenConfig

那么在定义上这个father.children就是一个子类,并且获取方式为:

Logger.getLogger(“father.children”);

代码中直接定义子类

即使没有在配置文件中显示的写出子类的定义,我们也可以在代码中通过名称来指定logger实例的继承关系:

Logger.getLogger(“father.children.children”);

上面这个语句就使得我们获得了一个继承自father.children的子类father.children.children。

继承关系的用处

继承的存在对我们最显著的影响是什么呢?

  • 个人理解是记录到子类上的log也会被父类接收!是的,正常情况,如果使用子类的实例记录一个log信息,那么这个子类的所有父类都会接收到log信息并且记录。如果我们把子类和父类的输出目的地都设置为一样,那么就会发现重复的log信息。
    比如我们使用以下代码段,并且把father,father.children的输出appender都设置为控制台输出(org.apache.log4j.ConsoleAppender)

    Logger logger=Logger.getLogger(“father.children.children”);
    Logger.info(“这是一个子类的子类log信息”);
    我们可以在控制台看到3条log信息,分别是由father.children.children、father.children、father上log进行了输出。
    这里要注意,father的级别被定义为DEBUG,但是我们输出的INFO信息页被father记录了,这个就表明了father接受到子类的log信息之后father的级别限定会被子类的覆盖掉。

  • 其实我个人并不是很理解这个继承关系会给我们带来什么样的好处,或许是某些部分的信息我们希望不仅被自己的log记录,还希望能被其他的log接收到。另外一个好处就是我们使用名字限定的方式在代码中动态获得一个没有在配置文件中指定的logger实例的时候,这个logger会继承那个父类的log配置。

RootLogger

还有需要注意的一点是,我们经常可以看到别人使用的配置文件里面会定义个:

log4j.rootLogger=DEBUG, append1, append2

  • 这里是对最高级的父类进行了rootLogger进行了配置限定,如果没有显式定义其他的Logger的话,那么所有代码中获取到的Logger实例都会继承这个配置。
  • 如果同时定义了其他Logger,并且那个Logger有一个继承的子Logger,那么那个子类Logger的继承关系是:children-> father ->rootLogger
  • 可以使用log4j.additivity.LOGNAME=false来屏蔽掉这种关系(注意LOGNAME是LOG的名称不是LOG的配置名)。

类实例Logger

我们经常使用的Logg.getLoggger(class)获取的Logger实例,如果需要配置这些Logger,在配置文件中定义其log规范使用class name来定位。

Log4j.logger.className= class_full_name
其含义就是使用class的全限定名来作为logger的名称,这样如果有需要的话我们可以对每个类都定义自己的log规范。
当然如果没有在配置文件里面配置这个全限定名字的logger,这个logger会继承rootLogger的配置,如果连rootLogger都没配置,那么log信息是无法被接收的。

Contents
  1. 1. Logger的理解
  2. 2. 继承关系
    1. 2.1. 父类
    2. 2.2. 用户自定义的Logger
    3. 2.3. 代码中直接定义子类
  3. 3. 继承关系的用处
  4. 4. RootLogger
  5. 5. 类实例Logger