log日志框架和LocationAwareLogger问题
来源:互联网 发布:开淘宝店需要什么费用 编辑:程序博客网 时间:2024/05/22 20:02
今天启动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" });
- }
- }
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);
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();
- }
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);
- }
- }
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); } }
获取配置信息初始化
- log日志框架和LocationAwareLogger问题
- log日志框架和LocationAwareLogger问题
- org.slf4j.spi.LocationAwareLogger.log
- org.slf4j.spi.LocationAwareLogger.log
- Log日志框架
- CXF发布中java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log问题
- java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log 造成的原因和解决方法
- java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log 造成的原因和解决方法
- 安卓 log日志框架
- Qt---log日志框架(1)
- java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log
- java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log
- CXF启动报错org.slf4j.spi.LocationAwareLogger.log
- 关于java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log
- myeclipse 遇到org.slf4j.spi.LocationAwareLogger.log的NoSuchMethodError错误
- activiti-explore java.lang.NoSuchMethodError org.slf4j.spi.LocationAwareLogger.log
- java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log异常处理
- Log日志框架-对原生Log进行简单封装
- hessian杂篇
- myeclipse10.0优化
- Java程序发送邮件的两种方法
- JSF之介绍篇
- 线性表的简单实现
- log日志框架和LocationAwareLogger问题
- UITableView for Android
- (转载)java synchronized详解
- 【转】Tapestry5和Eclipse的整合
- Java的Servlet调用服务器上的html文件直接在客户端打开
- Kii Cloud后端特性分析
- SideNavigation—仿facebook菜单效果
- JAVA直接本地HTML和TXT文件。
- java中hashcode和equal详解