zoukankan      html  css  js  c++  java
  • log日志框架和LocationAwareLogger问题

    遇到了同样的问题,

    我的解决办法是在pom.xml中增加如下配置,去除对于jcl-over-slf4j.jar的依赖。

        <exclusions>
                    <exclusion>
                        <artifactId>jcl-over-slf4j</artifactId>
                        <groupId>org.slf4j</groupId>
                    </exclusion>
                </exclusions>

    顺便转载下大神解答:

    转载自:http://blog.csdn.net/xian00000/article/details/10013395

    今天启动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.测试类

     java代码

    1. package com.taobao.wuzhong.log;  
    2.   
    3. import org.apache.commons.logging.Log;  
    4. import org.apache.commons.logging.LogFactory;  
    5. import org.junit.Test;  
    6. import org.slf4j.Logger;  
    7. import org.slf4j.LoggerFactory;  
    8.   
    9. /** 
    10.  * DESC: 
    11.  *  
    12.  * Copyright: Copyright 2011 m.taobao.com 
    13.  *  
    14.  * @author wuzhong@taobao.com 
    15.  * @time 2011-4-6 下午03:42:11 
    16.  * @version 1.0 
    17.  **/  
    18. public class LogTest {  
    19.   
    20.     // Logback tries to find a file called logback.groovy in the classpath.  
    21.     // If no such file is found, logback tries to find a file called  
    22.     // logback-test.xml in the classpath.  
    23.     // If no such file is found, it checks for the file logback.xml in the  
    24.     // classpath..  
    25.     // If neither file is found, logback configures itself automatically using  
    26.     // the BasicConfigurator which will cause logging output to be directed to  
    27.     // the console.  
    28.     @Test  
    29.     public void test() {  
    30.                 //commons-logging的方式获取  
    31.         Log log = LogFactory.getLog(LogTest.class);  
    32.                 //slf4j直接的方式获取,推荐用这个  
    33.         Logger log2 = LoggerFactory.getLogger(LogTest.class);  
    34.         log.debug("eeeeee {} {} {}");  
    35.         log2.debug("{} {} {}", new String[] { "a", "b", "c" });  
    36.     }  
    37.   
    38. }  

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

     public Log getInstance(String name) throws LogConfigurationException {

    1. Log instance = null;    
    2. // protect against concurrent access of loggerMap    
    3. synchronized (this) {    
    4.   instance = (Log) loggerMap.get(name);    
    5.   if (instance == null) {    
    6.     Logger logger = LoggerFactory.getLogger(name);   //slf4j的方式,代理过去了    
    7.     if(logger instanceof LocationAwareLogger) {    
    8.       instance = new SLF4JLocationAwareLog((LocationAwareLogger) logger);  //包装了一层,做适配    
    9.     } else {    
    10.       instance = new SLF4JLog(logger);    
    11.     }    
    12.     loggerMap.put(name, instance);    
    13.   }    
    14. }    
    15. return (instance);    


     

    loggerFactory 会调用getILoggerFactory().getlOgger()

    1. LoggerFactory.java    
    2.  public static ILoggerFactory getILoggerFactory() {    
    3.     if (INITIALIZATION_STATE == UNINITIALIZED) {    
    4.       INITIALIZATION_STATE = ONGOING_INITILIZATION;    
    5.       performInitialization();    
    6.     
    7.     }    
    8.     switch (INITIALIZATION_STATE) {    
    9.     case SUCCESSFUL_INITILIZATION:    
    10.       return getSingleton().getLoggerFactory();    
    11.     case FAILED_INITILIZATION:    
    12.       throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);    
    13.     case ONGOING_INITILIZATION:    
    14.       // support re-entrant behavior.    
    15.       // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106    
    16.       return TEMP_FACTORY;    
    17.     }    
    18.     throw new IllegalStateException("Unreachable code");    
    19.   }    
    20.     
    21.  private final static void performInitialization() {    
    22.     bind();    
    23.     versionSanityCheck();    
    24.     singleImplementationSanityCheck();    
    25.     
    26.   }    

    这里的bind很关键,这里动态的绑定了slf4j-api的实现机制

    1. static {    
    2.     SINGLETON.init();    
    3.   }    
    4.     
    5.   /**  
    6.    * Package access for testing purposes.  
    7.    */    
    8.   void init() {    
    9.     try {    
    10.       try {    
    11.         new ContextInitializer(defaultLoggerContext).autoConfig();    
    12.       } catch (JoranException je) {    
    13.         Util.reportFailure("Failed to auto configure default logger context",    
    14.             je);    
    15.       }    
    16.       StatusPrinter.printInCaseOfErrorsOrWarnings(defaultLoggerContext);    
    17.       contextSelectorBinder.init(defaultLoggerContext, KEY);    
    18.       initialized = true;    
    19.     } catch (Throwable t) {    
    20.       // we should never get here    
    21.       Util.reportFailure("Failed to instantiate ["    
    22.           + LoggerContext.class.getName() + "]", t);    
    23.     }    
    24.   }    


    获取配置信息初始化

    1. autoConfig ….    
    2. public URL findURLOfDefaultConfigurationFile(boolean updateStatus) {    
    3.     ClassLoader myClassLoader = Loader.getClassLoaderOfObject(this);    
    4.     URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);    
    5.     if (url != null) {    
    6.       return url;    
    7.     }    
    8.     
    9.     url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader);    
    10.     if (updateStatus) {    
    11.       statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url);    
    12.     }    
    13.     if (url != null) {    
    14.       return url;    
    15.     }    
    16.     
    17.     url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader);    
    18.     if (updateStatus) {    
    19.       statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url);    
    20.     }    
    21.     return url;    
    22.   }    
    23.     
    24.   public void autoConfig() throws JoranException {    
    25.     StatusListenerConfigHelper.installIfAsked(loggerContext);    
    26.     URL url = findURLOfDefaultConfigurationFile(true);    
    27.     if (url != null) {    
    28.       configureByResource(url);    
    29.     } else {    
    30.       BasicConfigurator.configure(loggerContext);    
    31.     }    
    32.   }    


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


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

    转载自 : http://myclqr.iteye.com/blog/1775541

    ------------------------------------------------------------------------------------

    用slf4j+logback替代commons-logging+log4j
    加载以下jar包:
    slf4j-api.jar
    logback-core.jar
    logback-classic.jar
    log4j-over-slf4j.jar
    jcl104-over-slf4j.jar
    同时删除commons-logging.jar和log4j.jar
    http://logback.qos.ch/translator/Welcome.do转换log4j.properties为logback.xml

  • 相关阅读:
    POJ 2349 Arctic Network
    OpenJudge 东方14ACM小组 / 20170123 06:Challenge 3
    OpenJudge 东方14ACM小组 / 20170123 02 岛屿
    Best Coder Lotus and Characters
    洛谷 P 1164 小A点菜
    楼房
    虫食算
    斗地主
    国王游戏
    最优贸易
  • 原文地址:https://www.cnblogs.com/widget90/p/7610034.html
Copyright © 2011-2022 走看看