简介
Simple Logging Facade for Java, 顾名思义,它是作为一个许多logging库(如log4j,logback,commons-logging等)的简单门面,提供一个简单统一的接口,从而使得最终用户能够很方便的使用和切换想要的logging实现。
可能你还是要问, 为什么要使用slf4j呢?
举个例子,如果你直接用log4j来写日志,你的代码里有100个地方是这样做的。
现在你想换成logback或其他的日志实现,你就需要修改100个地方。
而如果使用slf4j来写入日志,因为多了一层绑定的过程,你只要切换你的依赖即可。
使用slf4j很简单,只要加入slf4j-api-xxx.jar、第三方日志实现及其binding包的依赖即可。
<!-- slf4j api --> |
接下来, 你就可以打印 Hello World
啦!
import org.slf4j.Logger; |
根据slf4j的介绍,
each SLF4J binding is hardwired at compile time to use one and only one specific logging framework
它是静态绑定的, 接下来,让我们一起来揭开绑定的神秘面纱吧。
绑定原理
这是官网的一张图, 这里展示了常见的一些log实现和绑定:
前面说过, slf4j是在静态绑定, 为什么这么说呢? 答案就在绑定实现的包中, 如下:
logback-classic.jar
slf4j-log4j.jar
如上图,可以发现都有org.slf4j.impl.StaticLoggerBinder
,
再看LoggerFactory.getLogger()时,即org.slf4j.LoggerFactory.getILoggerFactory
的调用hierarchy:
其中bind()内部是我们想要的:
|
如代码,绑定方法bind(),首先通过findPossibleStaticLoggerBinderPathSet():staticLoggerBinderPathSet
来获取classpath中可能的binder paths, 如下:Enumeration<URL> ClassLoader.getSystemResources(String STATIC_LOGGER_BINDER_PATH)
其中STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"。
多个绑定存在的情况
当发生多个绑定同时存在时,官方的说明是这样的:
The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging framework/implementation and bind with it. The way SLF4J picks a binding is determined by the JVM and for all practical purposes should be considered random.
实际运行结果并结合以上代码,当返回的URL有多个时,reportMultipleBindingAmbiguity()会打印出警告:
Class path contains multiple SLF4J bindings. |
然后reportActualBinding()再打印出真正被加载的StaticLoggerBinder
的class name,比如:Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
为了避免这种问题,可以使用maven的全局排除依赖来保证只会出现某一个实现。
more info -> http://www.slf4j.org/codes.html
MDC (Mapped Diagnostic Context )
这个功能只有log4j和logback支持。
具体内容请查看log4j和logback部分。