遇到了同样的问题,

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

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. switch (INITIALIZATION_STATE) {
  8. case SUCCESSFUL_INITILIZATION:
  9. return getSingleton().getLoggerFactory();
  10. case FAILED_INITILIZATION:
  11. throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
  12. case ONGOING_INITILIZATION:
  13. // support re-entrant behavior.
  14. // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
  15. return TEMP_FACTORY;
  16. }
  17. throw new IllegalStateException("Unreachable code");
  18. }
  19. private final static void performInitialization() {
  20. bind();
  21. versionSanityCheck();
  22. singleImplementationSanityCheck();
  23. }

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

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

获取配置信息初始化

  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. url = Loader.getResource(TEST_AUTOCONFIG_FILE, myClassLoader);
  9. if (updateStatus) {
  10. statusOnResourceSearch(TEST_AUTOCONFIG_FILE, myClassLoader, url);
  11. }
  12. if (url != null) {
  13. return url;
  14. }
  15. url = Loader.getResource(AUTOCONFIG_FILE, myClassLoader);
  16. if (updateStatus) {
  17. statusOnResourceSearch(AUTOCONFIG_FILE, myClassLoader, url);
  18. }
  19. return url;
  20. }
  21. public void autoConfig() throws JoranException {
  22. StatusListenerConfigHelper.installIfAsked(loggerContext);
  23. URL url = findURLOfDefaultConfigurationFile(true);
  24. if (url != null) {
  25. configureByResource(url);
  26. } else {
  27. BasicConfigurator.configure(loggerContext);
  28. }
  29. }

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

总结: 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

log日志框架和LocationAwareLogger问题的更多相关文章

  1. Spring Boot Log 日志使用教程

    我们编写任何 Spring Boot 程序,可能绕不开的就是 log 日志框架(组件). 在大多数程序员眼中日志是用来定位问题的.这很重要. 本项目源码下载 注意本项目提供的源码已在后期重新编写,有部 ...

  2. scrapy框架之log日志

    scrapy中的debug信息 在scrapy中设置log 1.在settings中设置log级别,在settings.py中添加一行: Scrapy提供5层logging级别: CRITICAL - ...

  3. Xposed框架Hook Android应用的所有类方法打印Log日志

    本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80954759 在进行Android程序的逆向分析的时候,经常需要Android程 ...

  4. Atitit.log日志技术的最佳实践attilax总结

    Atitit.log日志技术的最佳实践attilax总结 1. 日志的意义与作用1 1.1. 日志系统是一种不可或缺的单元测试,跟踪调试工具1 2. 俩种实现[1]日志系统作为一种服务进程存在 [2] ...

  5. 解读ASP.NET 5 & MVC6系列(9):日志框架

    框架介绍 在之前的.NET中,微软还没有提供过像样的日志框架,目前能用的一些框架比如Log4Net.NLog.CommonLogging使用起来多多少少都有些费劲,和java的SLF4J根本无法相比. ...

  6. Java日志框架:SLF4J,Common-Logging,Log4J,Logback说明

    Log4j  Apache的一个开放源代码项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台.文件.GUI组件.甚至是套接口服务 器.NT的事件记录器.UNIX Syslog守护进程等 ...

  7. java日志框架slf4j与log4j

    日志记录自然是非常重要的,但恐怕能记住slf4j与log4j等日志框架配置的人就很少了,这个东西不难,只是配置好后很少会去动它,开发新项目一般也是从其他项目拷贝,或者参照文档 废话不多说,先说log4 ...

  8. Moon转告给你一个比Log4net更好日志框架--TracerX Logger 及其对应的日志查看器

    一.介绍 TracerX logger是一个易于上手,且拥有众多高级特性的.NET日志框架. 它能够发送输出结果到多目的地(循环文件.事件日志等....).它也能生成文本和二进制文件.它拥有一个强大的 ...

  9. lombok+slf4j+logback SLF4J和Logback日志框架详解

    maven 包依赖 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lomb ...

随机推荐

  1. Eclipse 安装应用SVN地址

    SVN插件下载地址及更新地址,你根据需要选择你需要的版本.现在最新是1.8.xLinks for 1.8.x Release:Eclipse update site URL: http://subcl ...

  2. 自行控制loadrunner的socket协议性能测试 (转)

    一前言 二任务的提出 三实现方案讨论 四技术要点讲解 如何开始录制一个最简单的收发数据包脚本 写日志文件 一行一行读数据包文件 字符串转换为十六进制数据包 发送自己定义的数据包 接收数据包到自定义缓冲 ...

  3. UVA 6475 Effective Infection Time

    You are estimating the threat level of quarantined zones that have been abandoned to the infection. ...

  4. android中点击事件的4种写法

    android中获取到一些控件(比如说按钮)时,一般会为其添加点击事件,android中的点击事件一共有4中写法. 假设在布局文件中声明如下 ....... <Button android:la ...

  5. Python解微分方程

    1.求解常微分方程的步骤: from sympy import * init_printing() #定义符号常量x 与 f(x) g(x).这里的f g还可以用其他字母替换,用于表示函数 x = S ...

  6. RGB格式等比例缩放

    原理为:将原始图像的每个像素通过一个比例关系式映射到相应的位置. /* lrgb: input 24bits rgb buffer srgb: output 24bits rgb buffer wid ...

  7. 转:C++ 关键字 inline详细介绍

    1.  内联函数 在C++中我们通常定义以下函数来求两个整数的最大值: int max(int a, int b) { return a > b ? a : b; } 为这么一个小的操作定义一个 ...

  8. leetCode 75.Sort Colors (颜色排序) 解题思路和方法

    Given an array with n objects colored red, white or blue, sort them so that objects of the same colo ...

  9. flume 中的 hdfs sink round 和roll

    http://blog.csdn.net/kntao/article/details/49278239 http://flume.apache.org/FlumeUserGuide.html#exec ...

  10. 敲敲SQL语句

    基本命令 查看数据库:show databases; 选择数据库:use mysql_crash; 连接数据库:需要:主机名,端口,合法用户名,用户口令 mysql -u ben -p -h loca ...