`

log日志框架和LocationAwareLogger问题

阅读更多

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

 

 

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 , 实现上还是比较简单的,很好的做到了接口和实现的分离,对今后的代码组织有一定的启发

分享到:
评论

相关推荐

    log4j日志框架

    通过以上介绍,我们可以看出Log4j日志框架在Java开发中的重要地位,它不仅简化了日志处理,还为故障排查、性能分析和系统监控提供了有力支持。正确使用和配置Log4j,将有助于提升软件质量和维护效率。

    采用jdk实现的日志框架

    在IT行业中,日志框架是不可或缺的工具,它主要用于记录应用程序运行时的详细信息,帮助开发者在调试、问题排查和性能优化过程中获取关键数据。"采用JDK实现的日志框架"是一个基于Java Development Kit(JDK)1.4中...

    用c++写的 log 日志文件

    此外,C++标准库并没有提供内置的日志框架,但在实际开发中,很多开发者会使用第三方库,如Glog、spdlog等,它们提供了更强大、更灵活的功能,例如异步日志处理、自定义格式化和日志过滤等。 总之,通过理解日志...

    [SSH+Maven+Bootstrap视频教程]_18. 测试 log4j 日志框架.zip

    【SSH+Maven+Bootstrap视频教程】第18章主要讲解了如何测试并应用Log4j日志框架,这是Java开发中的一个关键组件,尤其在系统监控、调试和错误跟踪方面发挥着重要作用。Log4j是Apache软件基金会的一个开放源代码项目...

    android日志框架jar包。log4j android版

    Log4j是一个广泛使用的Java日志框架,在服务器端和桌面应用中非常常见。不过,Log4j原生并不直接支持Android平台,因为它依赖于一些Android系统不包含的库。但有一些开发者社区提供了对Android的适配版本,让Log4j...

    c#log日志类和日志分析器(源码)

    本文将深入探讨“c# log日志类和日志分析器”的相关知识点,包括日志的创建、存储、分析以及提供的源码在实际项目中的应用。 首先,让我们了解什么是日志。日志是程序运行过程中产生的事件记录,这些记录包含了...

    Log4net日志管理框架.pdf

    Log4net是一个强大的日志管理框架,广泛应用于各种软件项目中,主要用于诊断和修复配置问题。该框架提供了丰富的功能,确保开发人员能够有效地记录、管理和分析应用中的日志信息。 **日志分级功能**是Log4net的核心...

    hana log日志空间占满处理.pdf

    当遇到"HANA log日志空间占满"的问题时,需要采取特定的步骤来处理,避免对系统造成灾难性的后果。以下是对标题和描述中所述知识点的详细解释: 1. **日志空间的重要性**: HANA的日志空间主要用于存储数据库的...

    JAVA日志框架适配-冲突解决方案.docx

    在JAVA中,日志框架可以分为两种:日志抽象/门面和日志实现。日志抽象/门面负责定义了一套统一的日志打印标准,如Logger对象、Level对象,不负责具体的日志打印,如输出到文件、配置日志内容格式等。slf4j(Simple ...

    tomcat8更换log4j记录日志

    此压缩包提供的资源是针对Tomcat8及其以下版本的日志管理解决方案,主要涉及Log4j这个流行的Java日志框架。下面将详细介绍如何在Tomcat8中替换或更新Log4j来记录日志。 首先,让我们了解一下Log4j。Log4j是Apache...

    Android下的自定义日志框架。移动开发一般没有必要引入第三方日志框架,可以自己编写

    在Android开发中,自定义日志框架是一种常见的实践,它可以帮助开发者更好地监控应用程序的运行状态,定位和解决问题。本文将详细介绍如何在Android环境下构建自己的日志框架,以及这样做的好处。 首先,Android...

    Java日志框架整合详情

    Java日志框架是Java开发中不可或缺的一部分,它用于记录应用程序运行过程中的各种信息,帮助开发者在出现问题时进行调试和分析。日志框架的选择和整合对于一个项目来说至关重要,因为它不仅影响到开发效率,还直接...

    无法打出log4j日志的问题排查

    在IT行业中,日志记录是调试和监控应用程序的关键部分,特别是对于Java开发者而言,Log4j是一个非常常用的日志框架。当我们遇到“无法打出log4j日志的问题”,这通常是由于配置、环境或代码实现中的某些错误导致的。...

    log日志组件总结

    Commons Logging的主要目标是解耦应用程序与特定的日志实现之间的依赖,这样可以在运行时动态切换日志框架,如log4j或java.util.logging。尽管如此,Commons Logging自身并不提供实际的日志记录功能,它只是一个接口...

    log日志的实现

    在IT行业中,日志(log)是至...综上所述,"log日志的实现"涉及了如何在Struts和iBatis等框架中配置和使用日志,以及如何通过最佳实践来提升日志的价值。通过对日志的合理管理,可以大大提高开发效率和系统的可维护性。

    Android下自定义日志框架

    7. **多线程安全**:在Android多线程环境中,日志框架需要确保线程安全,避免并发问题。 实现自定义日志框架时,可以创建一个`Logger`类,包含上述各种日志级别方法,并在其中实现日志输出的逻辑。例如: ```java ...

    log4j.rar java写LOG日志的驱动

    Log4j是Apache组织开发的一个开源日志框架,它是Java日志处理领域的经典工具,因其高效、灵活和可扩展性而广受欢迎。 **一、Log4j的基本概念** 1. **Logger(日志器)**:日志的主体,用于创建和管理日志记录。每...

    log4cplus开源的C++日志框架

    **log4cplus** 是一个基于C++的开源日志框架,它的设计灵感来源于Java社区中的log4j,旨在提供一种高效、灵活且易于使用的日志记录解决方案。这个框架允许开发者在C++程序中方便地记录调试信息,帮助追踪代码问题、...

    Log 日志配置

    本文将深入探讨"Log日志配置"的相关知识点,包括日志的重要性、常用日志框架、配置细节以及如何通过日志记录运行结果和参数。 一、日志的重要性 1. 错误排查:当程序出现异常时,日志记录可以帮助开发者快速定位...

    开源框架log4cpp和日志模块实现.pdf

    log4cpp是一个流行的开源日志框架,源自Java的日志处理项目log4j,它为C++程序员提供了灵活的日志记录功能。框架的核心理念是通过Category(分类)、Appender(输出器)、Layout(格式化器)和Priority(优先级)等...

Global site tag (gtag.js) - Google Analytics