log日志框架和LocationAwareLogger问题_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > log日志框架和LocationAwareLogger问题

log日志框架和LocationAwareLogger问题

 2013/5/19 14:11:21  myclqr  程序员俱乐部  我要评论(0)
  • 摘要:今天启动tomcat服务失败,碰到异常情况如下java.lang.NoSuchMethodError:org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)Vatorg.apache.commons.logging.impl.SLF4JLocationAwareLog.info(SLF4JLocationAwareLog
  • 标签:问题

今天启动tomcat服务失败,碰到异常情况如下

java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
??? at org.apache.commons.logging.impl.SLF4JLocationAwareLog.info(SLF4JLocationAwareLog.java:159)

?

?

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

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

?

?

?

?

?

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

?


?

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

?


?

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

?

?

?

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

?

?

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

?

?

?

?

?

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

?

1.测试类

?

?

class="java" name="code">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.
	@Test
	public 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框架应该很好的诠释了 facade , adapter , 实现上还是比较简单的,很好的做到了接口和实现的分离,对今后的代码组织有一定的启发

发表评论
用户名: 匿名