PSJay Blog

#FIXME, seriously

说说 Log4j

| Comments

废话

又到周末了,无聊。当然其实还有很多事情没有做,就是拖延嘛。每到这个时候,就可以写 Blog 来消遣和打发时间了。昨天初体验 Readability 看了看 log4j 的手册,那今天就写这个了。

它是什么

说白了,就是个 log 类库。

核心组件

log4j 由这三个重要的组件一起工作来完成日志工作:

  • Logger(v1.2 之前叫做 Category):用来记录日志。

  • Appender: 用来决定将日志输出到哪儿。

  • Layout:用来格式化日志输出。

然后就可以开始逐个介绍它们了。

Logger

Logger 组件用来记录日志,它仅仅只做记录的工作,和输出及输出格式无关。例如:

1
2
3
Logger logger = Logger.getLogger("loggerName");

logger.info("log something.");

这段代码用 logger 记录了一条级别为 INFO 的日志。

可以看到,Logger 是有名字的。另外,Logger 之间是有继承关系的。这两点都和 Java 包相似。例如,名为『x.y』的 Logger 是名为『x.y.z』的 Logger 的父 Logger。有一个特殊的 Logger,叫做 root Logger,它是所有 Logger 的祖先。因为这种缘故,用本类的 Class 实例给 Logger 取名字是一个很不错的策略,例如:

1
2
3
4
5
public class MyClass {
  private static logger = Logger.getLogger(MyClass.class);

  // ......
}

除了 root Logger 之外,所有的 Logger 都可以用 Logger.getLogger(String loggerName) 方法来获取,而 root 要用 Logger.getRootLogger()来获取。

Logger 可以被设置一个日志记录等级,log4j本身提供了这一些:

TRACE,
DEBUG,
INFO,
WARN,
ERROR,
FATAL

记录等级是有大小关系的,从字面上看,它们一个比一个值得让人注意,所以从上到下,等级一个比一个大。

前面提到了 Logger 之间是有继承关系的,若一个 Logger 本身没有指定日志记录等级,那么它的日志记录等级就会继承自距离最近的被指定了日志记录等级的祖先。Logger 将会记录日志等级大于等于它自己的日志记录等级的日志。

Appender

Appender 用来指定日志记录的目标,例如可以是控制台、文件,或者是其他什么地方。

Appender 必须附着在 Logger 上,一个 Logger 也可以有多个 Appender。另外,Appender 是可以累加的,也就是说,一个 Logger 的 Appender 除了自身附着的之外,还会累加上祖先 Logger 的 Appender,除非祖先 logger 将 Additivity Flag 设置为了 false。

Layout

Layout 用来格式化日志。例如 PatternLayout 就是一种类似与 C 语言的 printf 函数的用法那样的 Layout。

配置

log4j 可以直接用代码,或者通过 properties 文件, XML 文件来进行配置。官方手册的例子已经解释得很清楚了,结合上述知识也很容易看懂,这里不赘述,简单地翻译一下默认初始化的过程:

  1. 检查系统属性 log4j.defaultInitOverride ,如果不为 false,则忽略以下全部过程。

  2. 将资源字符串变量设置为系统属性 log4j.configuration 的值,log4j.configuration 的默认值是『log4j.properties』 。

  3. 尝试将资源字符串变量转换为一个 URL。

  4. 如果资源字符串变量不能转换为 URL,例如抛出了一个 MalformedURLException,就调用 org.apache.log4j.helpers.Loader.getResource(resource, Logger.class) 方法来从 classpath 下面寻找资源,这个方法本身也返回一个 URL。注意,字符串 『log4j.properties』 不能直接转换成 URL。

  5. 如果依然找不到 URL,就终止这个初始化过程。不然,log4j 就根据 URL 来进行配置。如果 URL 以『.xml』结尾,就会用 DOMConfigurator 来进行配置,不然,就用 PropertyConfigurator 来进行配置。你也可以通过设置系统属性 log4j.configuratorClass 来指定自定义配置器(Configurator),log4j.configuratorClass 的值必须是你的自定义配置器类的全限定名,这个类也必须实现 Configurator 接口。

Comments