各种log的加载过程

1. 概述

现在的log框架越来越多,目前我们系统用有使用的包括commons-logging,log4j,slf4j(还有 一个号称更快的logback暂时基本没有用到),而这些log系统又常常依赖于一些jar包顺序和静态配置,导致比较混乱,甚至出现一些难以重现的诡异 问题,因此在这里就各个log系统的初始化过程介绍一下,方便以后排查问题。
本文主要侧重多个日志系统的混合使用和加载,对于日志级别,格式等等方面不涉及。

2. 介绍

2.1. commons-logging

apache提供的日志门面接口,主要是为了避免程序和具体的log耦合。

基本使用方法:

首先需要引入commons-logging.jar(通过maven或者其他方法皆可),然后这样使用就可以了

  1. Log logger = LogFactory.getLog(TestCommonsLogging.class);
  2. logger.debug(“test debug”);

初始化过程:

其中LogFactory是实现解耦的关键,他使用log系统的查找顺序是这样的:
1. 寻找当前factory中名叫org.apache.commons.logging.Log配置属性的值。注意值可以通过java代码设置,但更多的是 在classpath中提供一个交commons-logging.properties的文件,设置在里面,比 如:org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JCategoryLog
如果classpath中有多个文件,在1.1版本之前,使用找到的第一个,1.1版本及其以后会在配置文件中定义一个优先级,使用优先级最高的。
2. 寻找系统中属性中名叫org.apache.commons.logging.Log的值。
3. 如果应用程序的classpath中有log4j,则使用相关的包装(wrapper)类(Log4JLogger)
4. 如果应用程序运行在jdk1.4的系统中,使用相关的包装类(Jdk14Logger)
5. 使用自带的简易日志包装类(SimpleLog)

2.2 slf4j

slf4j和commons-logging功能类似

基本使用方法:

首先要引入slf4j-api-1.6.4jar,然后比如要支持log4j,就引入slf4j-log4j12-1.6.4jar

  1. Logger logger = LoggerFactory.getLogger(Slf4jTest.class);
  2. logger.debug(“test debug”);

初始化过程:

SLF4J没有通过配置文件来指明使用哪个log,而是通过引入适配jar包来指定。如果引入了两个桥接包,就看谁在classpath的前面了。(事实 上,每个桥接包中都有一个同名类org.slf4j.impl.StaticLoggerBinder,通过 org.slf4j.LoggerFactory的静态代码块加载
loggerFactory = StaticLoggerBinder.SINGLETON.getLoggerFactory();)


2.3 log4j

这个就不用介绍了,大家都懂的。

基本使用方法

  1. Logger logger =org.apache.log4j.Logger.getLogger(Log4jTest.class);
  2. logger.debug(“test debug”);

初始化过程:

1.检查系统变量Log4j.configuration,如果有值,使用这个值设定的配置文件,否则先尝试在classpath中加载 log4j.xml,没有再尝试加载log4j.properties.找到对应的配置文件后,调用对应的DOMConfigurator或者 PropertyConfigurator来初始化
configurator.doConfigure(url, hierarchy);
2.如果都没有配置,那么需要在应用中显示调用DOMConfigurator或者PropertyConfigurator来初始化。
3.如果在程序执行的过程中,代码调用了一次XXXConfigurator.configure(),所有对应的logger的设置都会随之改变。

3. 分析一个实际例子

我们在启动jetty的时候,jetty用的是slf4j,我们在lib中放置了slf4j-api-1.6.4jar,slf4j-log4j12-1.6.4jar和log4j.properites,所以会使用log4j打印log。

在应用起来的过程中,由于是自己的classloader,不会复用jetty本身的log配置,首先加载的 是,dragoon的filter用了slf4j,而这个时候应用的log4j系统还没有初始化,于是就在类路径的jar包中随便找到了第一个 log4j.prpperties,然后正好输出到了控制台。(因此在启动中有几行dragoon的控制台输出)

servelt初始化后,webx利用commons-logging包装了log4j,在war包的WEB-INF下查找log4j配置文件并使用,覆 盖掉开始dragoon初始化的log4j提醒,这样在应用中所有的log4j都会使用新的这套配置了。因此除了系统的应用代码外,二方库和3方库如果使 用了log4j,commons-logging和slf4j的方式打log,都会使用我们WEB-INF下的log4j配置。未特殊设置的,都会打印到 root对应的appender上面去。

4. 参考文献:

http://commons.apache.org/logging/commons-logging-1.1.1/guide.html
http://www.slf4j.org/manual.html
http://logging.apache.org/log4j/1.2/manual.html

猜你喜欢

转载自wsmajunfeng.iteye.com/blog/1631292