一、环境搭建

我们以log4j为例,探寻slf4j与log4j的绑定过程。

1.Java类

public class Slf4jBind {
public static void main(String[] args) {
Logger LOGGER = LoggerFactory.getLogger(Slf4jBind.class);
LOGGER.info("slf4j hello world");
}
}

2.log4j.properties文件

来自https://docs.oracle.com/cd/E29578_01/webhelp/cas_webcrawler/src/cwcg_config_log4j_file.html

log4j.rootLogger=ERROR,stdout
log4j.logger.com.endeca=INFO
# Logger for crawl metrics
log4j.logger.com.endeca.itl.web.metrics=INFO

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p\t%d{ISO8601}\t%r\t%c\t[%t]\t%m%n

3.Maven的pom.xml中添加如下依赖

<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.4</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>

其中,slf4j-api定义接口的包。

slf4j-log4j12为slf4j与logj之间的桥接包。

log4j为log4j的具体实现包。

4.单步跟踪

在main函数处打断点,debug模式下单步跟踪即可

二、slf4j绑定log4j流程

main函数中调用LoggerFactory.getLogger时,将依次执行下面的函数。

slf4j对LoggerFactroy的说明如下:

LoggerFactory是为各个日志API生成Logger的帮助类。

如log4j,logback,jdk 1.4 logging,也支持NOPLogger,SimpleLogger。

LoggerFactory内部封装了ILoggerFactory,具体的ILoggerFactory与LoggerFactory在编译期(complile time)绑定。

public static Logger getLogger(Class clazz) {
return getLogger(clazz.getName());
} public static Logger getLogger(String name) {
ILoggerFactory iLoggerFactory = getILoggerFactory();
return iLoggerFactory.getLogger(name);
}

/
* ILoggerFactory instance is bound with this class at compile time.
*
* @return the ILoggerFactory instance in use
*/
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITILIZATION;
performInitialization();

}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITILIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITILIZATION:
return NOP_FALLBACK_FACTORY;
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() {
//对具体的日志框架实现是否仅有一个进行check
singleImplementationSanityCheck();
//与具体的日志框架绑定
bind();
if (INITIALIZATION_STATE == SUCCESSFUL_INITILIZATION) {
//版本依赖兼容性check
versionSanityCheck();
}
}

1.对具体的日志框架实现是否仅有一个进行check。

1).判断classpath下是否有多个org/slf4j/impl/StaticLoggerBinder.class

2).如果有多个,将提示有多个SLF4J的绑定包。

private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";

private static void singleImplementationSanityCheck() {
try {
ClassLoader loggerFactoryClassLoader = LoggerFactory.class
.getClassLoader();
Enumeration paths;
if (loggerFactoryClassLoader == null) {
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
} else {
paths = loggerFactoryClassLoader
.getResources(STATIC_LOGGER_BINDER_PATH);
}
// use Set instead of list in order to deal with bug #138
// LinkedHashSet appropriate here because it preserves insertion order during iteration
Set implementationSet = new LinkedHashSet();
while (paths.hasMoreElements()) {
URL path = (URL) paths.nextElement();
implementationSet.add(path);
}
if (implementationSet.size() > 1) {
Util.report("Class path contains multiple SLF4J bindings.");
Iterator iterator = implementationSet.iterator();
while(iterator.hasNext()) {
URL path = (URL) iterator.next();
Util.report("Found binding in [" + path + "]");
}
Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
}
} catch (IOException ioe) {
Util.report("Error getting resources from path", ioe);
}
}

2.绑定具体的日志框架

根据找到的org/slf4j/impl/StaticLoggerBinder.class,执行StaticLoggerBinder.getSingleton()进行绑定。

private final static void bind() {
try {
// the next line does the binding
StaticLoggerBinder.getSingleton();//绑定
INITIALIZATION_STATE = SUCCESSFUL_INITILIZATION;
emitSubstituteLoggerWarning();
} catch (NoClassDefFoundError ncde) {
String msg = ncde.getMessage();
if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
INITIALIZATION_STATE = NOP_FALLBACK_INITILIZATION;
Util
.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
Util.report("Defaulting to no-operation (NOP) logger implementation");
Util.report("See " + NO_STATICLOGGERBINDER_URL
+ " for further details.");
} else {
failedBinding(ncde);
throw ncde;
}
} catch(java.lang.NoSuchMethodError nsme) {
String msg = nsme.getMessage();
if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
INITIALIZATION_STATE = FAILED_INITILIZATION;
Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
Util.report("Your binding is version 1.5.5 or earlier.");
Util.report("Upgrade your binding to version 1.6.x. or 2.0.x");
}
throw nsme;
} catch (Exception e) {
failedBinding(e);
throw new IllegalStateException("Unexpected initialization failure", e);
}
}

因为具体的日志框架为log4j,StaticLoggerBinder返回的为Log4j的LoggerFactory。

private final ILoggerFactory loggerFactory;

private StaticLoggerBinder() {
loggerFactory = new Log4jLoggerFactory();
try {
Level level = Level.TRACE;
} catch (NoSuchFieldError nsfe) {
Util
.report("This version of SLF4J requires log4j version 1.2.12 or later. See also http://www.slf4j.org/codes.html#log4j_version");
}
}
 

经过以上步骤,slf4j将于具体的日志框架log4j绑定。

如下所示,ILoggerFactory实际返回类型为Log4jLoggerFactory。

并调用Log4jLoggerFactory中的getLogger方法返回Log4jLogger用于log写入。

slf4j日志框架绑定机制的更多相关文章

  1. 深入理解Logger日志——框架绑定原理

    深入理解Logger日志--框架绑定原理 说到Logger日志的动态绑定,主要归功与Slf4j,在之前的文章也说过,Slf4j是类似于Apache Common-Logging,英文为Simple L ...

  2. slf4j日志框架

  3. Slf4j+Log4j日志框架入门

    (一).日志系统介绍 slf4j,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统.简答的讲就是slf4j是一系列的 ...

  4. Java日志框架Slf4j+Log4j入门

    一.日志系统介绍 slf4j,即简单日志门面(Simple Logging Facade for Java),不是具体的日志解决方案,它只服务于各种各样的日志系统.简答的讲就是slf4j是一系列的日志 ...

  5. java日志框架系列(1):slf4j框架简介及依赖

    1.slf4j日志框架 1.简介 slf4j只是是日志规范,即只定义了接口,并没有实现这些接口. SLF4J的全称是Simple Logging Facade for Java,即简单日志门面.SLF ...

  6. java日志框架与日志系统

    日志框架:提供日志调用的接口,实际的日志输出委托给日志系统实现. JCL(Jakarta Commons Logging):比较流行的日志框架,很多框架都依赖JCL,例如Spring等. SLF4j: ...

  7. Java日志框架(Commons-logging,SLF4j,Log4j,Logback)

    简介 在系统开发中,日志是很重要的一个环节,日志写得好对于我们开发调试,线上问题追踪等都有很大的帮助.但记日志并不是简单的输出信息,需要考虑很多问题,比如日志输出的速度,日志输出对于系统内存,CPU的 ...

  8. 拨云见日,彻底弄清楚Java日志框架 log4j, logback, slf4j的区别与联系

    log4j 以及 logback, slf4j 官网 日志框架的困惑 作为一个正常的项目,是必须有日志框架的存在的,没有日志,很难追踪一些奇奇怪怪的系统问题. 但是,我们经常在项目的依赖中,见到奇奇怪 ...

  9. 日志框架(Log4J、SLF4J、Logback)--日志规范与实践

    文章目录 一.Log4j 1.1新建一个Java工程,导入Log4j包,pom文件中对应的配置代码如下: 1.2resources目录下创建log4j.properties文件. 1.3输出日志 1. ...

随机推荐

  1. Dart异步与消息循环机制

    Dart与消息循环机制 翻译自https://www.dartlang.org/articles/event-loop/ 异步任务在Dart中随处可见,例如许多库的方法调用都会返回Future对象来实 ...

  2. Top 10 Algorithms of 20th and 21st Century

    Top 10 Algorithms of 20th and 21st Century MATH 595 (Section TTA) Fall 2014 TR 2:00 pm - 3:20 pm, Ro ...

  3. Poloniex API 文档

    Examples PHP wrapper by compcentral: http://pastebin.com/iuezwGRZ Python wrapper by oipminer: http:/ ...

  4. php面向对象--继承

    继承 extends 关键字来继承类 被继承的类,我们称之为父类 继承后的类,我们称之为子类 子类继承父类非私有的属性和方法 public 在本类,子类,以及类的外部都访问 protected 保护型 ...

  5. C++ 带有通配符*与?的字符串匹配

    题目:两个字符串,一个是普通字符串,另一个含有*和?通配符,*代表零个到多个任意字符,?代表一个任意字符,通配符可能多次出现.写一个算法,比较两个字符串是否相等. 发现许多公司笔试面试都有这道题目,于 ...

  6. java 多线程 day13 condition 线程通信

    /** * Created by chengtao on 17/12/5. * Condition 类似 wait和notify,解决线程间的同步问题 */ import java.util.conc ...

  7. 压力测试工具MySQL mysqlslap

    MySQL mysqlslap压测 2016-09-12 17:49 by pursuer.chen, 771 阅读, 0 评论, 收藏, 编辑 介绍 mysqlslap是mysql自带的一个性能压测 ...

  8. HALCON串口通讯程序

    串口通讯程序   * Note: This example is meant to demonstrate the use of the serial interface * of HALCON.   ...

  9. yii2美化url

    http://blog.csdn.net/xundh/article/details/45418265

  10. springBoot 整合 RabbitMQ 的坑

    1.Consumer raised exception, processing can restart if the connection factory supports it. Exception ...