首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

log日记框架的学习

2012-12-23 
log日志框架的学习?Commons-log + log4j 这黄金搭档一直以来都让我们很省心,很好的完成了日志的需求。但是

log日志框架的学习

?

Commons-log + log4j 这黄金搭档一直以来都让我们很省心,很好的完成了日志的需求。但是随着技术的变更和对性能的追求,slf4j 和 logback 这对后起之秀的到来好像打破了原本很平静的日志系统,频繁的出现包冲突...?

?? ? ? 和平的日子不在了,让我们一起来看看究竟发生了什么...

?

?

首先看看这些个包,特别是slf4j引入后就引入了一大堆包之后就有点懵了。


log日记框架的学习

为什么commons-logging和jcl-over-slf4j会有冲突呢?看一下它们的类结构


log日记框架的学习

很清晰的可以看到jcl-over-slf4j 重写了 commons-logging...

?

还有slf4j-api的实现呢,同样看类:

log日记框架的学习

其实就这么简单,往往看了代码之后才发现错误是这么显而易见。。。

?

?

顺着研究,继续看一下slf4j的源码及流程

1.测试类

?

package com.taobao.wuzhong.log;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.junit.Test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * DESC: *  * Copyright: Copyright 2011 m.taobao.com *  * @author wuzhong@taobao.com * @time 2011-4-6 下午03:42:11 * @version 1.0 **/public class LogTest {// Logback tries to find a file called logback.groovy in the classpath.// If no such file is found, logback tries to find a file called// logback-test.xml in the classpath.// If no such file is found, it checks for the file logback.xml in the// classpath..// If neither file is found, logback configures itself automatically using// the BasicConfigurator which will cause logging output to be directed to// the console.@Testpublic void test() {                //commons-logging的方式获取Log log = LogFactory.getLog(LogTest.class);                //slf4j直接的方式获取,推荐用这个Logger log2 = LoggerFactory.getLogger(LogTest.class);log.debug("eeeeee {} {} {}");log2.debug("{} {} {}", new String[] { "a", "b", "c" });}}
?

?

logFactory.getLog 会调用内部静态变量 Slf4jLogFactory.getInstance方法,如下:

?

?public Log getInstance(String name) throws LogConfigurationException {

    Log instance = null;    // protect against concurrent access of loggerMap    synchronized (this) {      instance = (Log) loggerMap.get(name);      if (instance == null) {        Logger logger = LoggerFactory.getLogger(name);   //slf4j的方式,代理过去了        if(logger instanceof LocationAwareLogger) {          instance = new SLF4JLocationAwareLog((LocationAwareLogger) logger);  //包装了一层,做适配        } else {          instance = new SLF4JLog(logger);        }        loggerMap.put(name, instance);      }    }    return (instance);  }

?

loggerFactory 会调用getILoggerFactory().getlOgger()

?

LoggerFactory.java public static ILoggerFactory getILoggerFactory() {    if (INITIALIZATION_STATE == UNINITIALIZED) {      INITIALIZATION_STATE = ONGOING_INITILIZATION;      performInitialization();    }    switch (INITIALIZATION_STATE) {    case SUCCESSFUL_INITILIZATION:      return getSingleton().getLoggerFactory();    case FAILED_INITILIZATION:      throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);    case ONGOING_INITILIZATION:      // support re-entrant behavior.      // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106      return TEMP_FACTORY;    }    throw new IllegalStateException("Unreachable code");  } private final static void performInitialization() {    bind();    versionSanityCheck();    singleImplementationSanityCheck();  }
这里的bind很关键,这里动态的绑定了slf4j-api的实现机制

?

static {    SINGLETON.init();  }  /**   * Package access for testing purposes.   */  void init() {    try {      try {        new ContextInitializer(defaultLoggerContext).autoConfig();      } catch (JoranException je) {        Util.reportFailure("Failed to auto configure default logger context",            je);      }      StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);      contextSelectorBinder.init(defaultLoggerContext, KEY);      initialized = true;    } catch (Throwable t) {      // we should never get here      Util.reportFailure("Failed to instantiate ["          + LoggerContext.class.getName() + "]", t);    }  }
?

获取配置信息初始化

?

autoConfig ….public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {    ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);    URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);    if (url != null) {      return url;    }    url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader);    if (updateStatus) {      statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url);    }    if (url != null) {      return url;    }    url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader);    if (updateStatus) {      statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url);    }    return url;  }  public void autoConfig() throws JoranException {    StatusListenerConfigHelper.installIfAsked(loggerContext);    URL url = findURLOfDefaultConfigurationFile(true);    if (url != null) {      configureByResource(url);    } else {      BasicConfigurator.configure(loggerContext);    }  }

?

最后画张流程图总结下,^_^


log日记框架的学习

?

?

总结: log框架应该很好的诠释了 facade , adapter , 实现上还是比较简单的,很好的做到了接口和实现的分离,对今后的代码组织有一定的启发

热点排行