SLF4J用户手册

来源:互联网 发布:wirelessmon mac版 编辑:程序博客网 时间:2024/06/05 10:01

SLF4J用户手册

    简单Java日志外观(SLF4J)提供了不同的日志框架,例如java.util.logginglogbacklog4j的外观。SLF4J允许最终用户在部署时插入期望的日志框架。请注意SLF4J意味着你的库或者应用只有一个强制的依赖,即slf4j-api-1.7.12.jar

    从1.6.0版本开始,如果在类路径没有发现绑定(的日志框架),那么SLF4J将会默认无操作。

    从1.7.0版本开始,在Logger接口中的打印方法提供可变参数的版本,即可以接受可变参数而不是Object[]数组。这个改变意味着SLF4J需要JDK 1.5以上的版本。在引擎盖的下面,Java编译器将方法中的可变参数转换为Object[]数组。这样,1.7.x编译器生成的Logger接口与1.6.x编译器生成的接口别无二致。因而断定,SLF4J 1.7.x版本完全无条件兼容1.6.x版本。

    从1.7.5版本开始,在日志的检索次数上有很大的改善。考虑到改善的范围,强烈建立用户迁移到1.7.5以上的版本。 

    从1.7.9版本开始,通过设置slf4j.detectLoggerNameMismatch系统属性为trueSLF4J可以自动识别错误命名的logger

Hello World

延续编程领域的传统,这里用一个例子说明使用SLF4J最简单的方式输出"Hello world"。首先,获取一个HelloWorld类的logger日志对象。这个logger对象反过来用于记录"Hello World"消息。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}

    为了运行这个例子,你首先需要下载slf4j的发布包,然后解压它。解压完后,将slf4j-api-1.7.12.jar添加到你的类路径中。

    编译并运行HelloWorld,在控制台将会有输出如下的结果:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".

SLF4J: Defaulting to no-operation (NOP) logger implementation

SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

    打印这个警告,是因为slf4j没有在类路径找到绑定(的日志框架)。

    一旦你在类路径中添加了一个绑定(的日志框架),警告就会消失。假设你添加了slf4j-simple-1.7.12.jar,这样你的类路径中包含下面两个jar包:

  1. slf4j-api-1.7.12.jar
  2. slf4j-simple-1.7.12.jar

    编译并运行HelloWorld ,现在在控制台将输出如下的结果:

0 [main] INFO HelloWorld - Hello World

典型的使用模式

下面的示例代码说明了SLF4J一个典型的使用模式。注意第15行的占位符{}的使用。参考FAQ的问题"What is the fastest way of logging?"了解更多详细信息。

 1: import org.slf4j.Logger;
 2: import org.slf4j.LoggerFactory;
 3: 
 4: public class Wombat {
 5:  
 6:   final Logger logger = LoggerFactory.getLogger(Wombat.class);
 7:   Integer t;
 8:   Integer oldT;
 9:
10:   public void setTemperature(Integer temperature) {
11:    
12:     oldT = t;        
13:     t = temperature;
14:
15:     logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
16:
17:     if(temperature.intValue() > 50) {
18:       logger.info("Temperature has risen above 50 degrees.");
19:     }
20:   }
21: } 

 

 

在部署时绑定日志框架

    正如之前提到的,SLF4J支持不同的日志框架。SLF4J发布包附带的几个jar包被称为“SLF4J绑定”,每一个绑定对应一种支持的框架:

slf4j-log4j12-1.7.12.jar 

绑定log4j 1.2版本,一个广泛使用的日志框架。也需要把log4j.jar包放到你的类路径中。

slf4j-jdk14-1.7.12.jar 

绑定java.util.logging,也被称为JDK 1.4日志。

slf4j-nop-1.7.12.jar

绑定NOP无操作,默默丢弃所有的日志。

slf4j-simple-1.7.12.jar

绑定简单实现(的日志框架),这个简单的日志框架将所有的事件输出到System.err。只有INFO级别以上的消息才被打印。这个绑定在小型应用程序可能会很有用。

slf4j-jcl-1.7.12.jar

绑定了Jakarta Commons Logging日志框架。这个绑定委派所有的SLF4J日志到JCL日志框架中。

logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)

本地实现。有一些与在SLF4J工程之外的SLF4J绑定,例如logback实现了SLF4J框架。Logbackch.qos.logback.classic.Logger类是SLF4Jorg.slf4j.Logger接口的直接实现。这样,联合使用SLF4Jlogback涉及到严格地零内存和计算开销。

    切换日志框架,只需要在类路径中替换slf4j的绑定。例如,要从java.util.logging切换到log4j,只需要将slf4j-jdk14-1.7.12.jar替换为slf4j-log4j12-1.7.12.jar即可。

SLF4J不依赖于任何特殊的类加载工具。每一个SLF4J绑定都是在编译时就硬编码使用一个并且只使用一个日志框架。例如,slf4j-log4j12-1.7.12.jar绑定在编译时使用log4j绑定。在你的代码中,除了slf4j-api-1.7.12.jar,你仅仅需要将一个且只有一个你选择的绑定丢到类路径中。不要在路径中放置1个以上的绑定。这里有个图来说明大概的意思。

    SLF4J的接口和它们不同的适配器是极其简单的。大多数熟悉Java语言的开发人员都应该能够在一个小时内读懂并完全理解这些代码。不需要知道类加载器的知识,SLF4J没有使用也没有直接访问任何类加载器。因而,SLF4J没有类加载器的问题或者在JCL中的内存泄漏。

    考虑到SLF4J接口和部署的简单性,新的日志框架的开发者应该觉得编写SLF4J绑定是很容易的。

 

4 库

    为了避免将日志框架强加给最终用户,组件和库的作者可能编码时紧靠SLF4J接口。这样,最终用户在部署时可能选择期望的日志框架,只需在类路径中插入相应的slf4j绑定即可。这个可能会发生改变的,要用另外一个绑定提换已经存在的绑定,并重启应用程序。这个方法证明是非常简单和稳定的。

    从SLF4J 1.6.0版本开始,如果没有在类路径中发现绑定,那么slf4j-api将会使用默认的无操作实现,丢弃所有的日志请求。这样,不会因为org.slf4j.impl.StaticLoggerBinder类丢失了抛出NoClassDefFoundError异常,SLF4J 1.6.0以上版本会发出一个绑定缺失的告警消息,继续丢弃所有的日志请求。例如,假设Wombat是与生物有关的框架,依赖SLF4J记录日志。为了避免强加一个日志框架给最终用户,Wombat的发布包包含了slf4j-api.jar包,但是没有绑定(特定的日志框架)。即使类路径中缺失了SLF4J绑定,Wombat的发布包仍然是即开即用的,不需要最终用户从SLF4J的网站上下载绑定。只有当最终用户决定使用日志了,他才需要安装与选择的日志框架对应的SLF4J绑定。

    基本规则:嵌入式的组件例如库或者框架不应该声明依赖于任何SLF4J的绑定,而是依赖于slf4j-api。当库声明了一个传递依赖于特定的绑定,绑定被强加给最终用户了,这是与SLF4J的目的相悖的。记住,声明非传递性依赖于绑定,例如测试,不要影响最终用户。

    在嵌入式组件中使用SLF4JFAQ中讨论了,有关的问题是日志配置,减少依赖和测试。

声明日志的工程依赖

    考虑到Maven的传递依赖规则,对于普通工程(不是库或者框架)声明日志依赖可以通过单一的依赖声明来完成。

    logback-classic:如果你想要使用logback-classic作为日志框架,你需要在pom.xml文件中声明"ch.qos.logback:logback-classic"依赖。除了logback-classic-1.0.13.jar包,这会将slf4j-api-1.7.12.jar包连同logback-core-1.0.13.jar包加入工程中。记住明确地声明依赖logback-core-1.0.13或者slf4j-api-1.7.12.jar是没有错的,有时可能是必要的。例如,根据Maven就近依赖原则,为了强加一个正确的版本给上述的artifact,就需要明确地声明。如下所示:

<dependency> 
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.0.13</version>
</dependency>

    log4j:如果你想要使用log4j作为日志框架,你需要在pom.xml文件中声明"org.slf4j:slf4j-log4j12"作为依赖。除了slf4j-log4j12-1.7.12.jar这会将slf4j-api-1.7.12.jar包连同log4j-1.2.17.jar包加入工程中。记住明确地声明log4j-1.2.17.jar或者slf4j-api-1.7.12.jar依赖,有时可能是必要的。例如,根据Maven就近依赖原则,为了强加一个正确的版本给上述的artifact,就需要明确地声明。如下所示:

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-log4j12</artifactId>
  <version>1.7.12</version>
</dependency>

    Java.util.logging:如果你想要使用java.util.logging作为日志框架,你需要在pom.xml文件中声明"org.slf4j:slf4j-jdk14"作为依赖。除了slf4j-jdk14-1.7.12.jar这会将slf4j-api-1.7.12.jar包连同log4j-1.2.17.jar包加入工程中。记住明确地声明slf4j-api-1.7.12.jar依赖,有时可能是必要的。例如,根据Maven就近依赖原则,为了强加一个正确的版本给上述的artifact,就需要明确地声明。如下所示:

<dependency> 
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-jdk14</artifactId>
  <version>1.7.12</version>
</dependency>

6 二进制兼容性

    SLF4J绑定指派一个工件,例如slf4j-jdk14.jarslf4j-log4j12.jar包用于将slf4j绑定到一个日志框架,分别是java.util.logginglog4j

    从客户端的角度看,所有版本的slf4j-api 都是兼容的。对于任意的NMslf4j-api-N.jar编译的客户端代码用slf4j-api-M.jar运行也非常好。只需要确保绑定的版本与slf4j-api.jar匹配。你不必担心你的工程中依赖所使用的slf4j-api.jar的版本。

    slf4j-api.jar版本和SLF4J绑定的版本混合使用可能会引发问题。例如,如果你使用slf4j-api-1.7.12.jar包,那么你应该也使用slf4j-simple-1.7.12.jar包,使用slf4j-simple-1.5.5.jar将无法工作。

    然而,从客户端的角度看,所有的slf4j-api的版本都是兼容的。对于任意的NMslf4j-api-N.jar编译的客户端代码如果用slf4j-api-M.jar运行也没问题。只需要确保绑定的版本与slf4j-api.jar相匹配。你不必担心你的工程中的依赖所使用的slf4j-api.jar的版本。你总是可以使用slf4j-api.jar的任意版本,只要slf4j-api.jar的版本和它的绑定版本相匹配,就可以工作的很好。

    在初始化时,如果SLF4J怀疑slf4j-api的版本和绑定的版本不匹配,它会发出一个怀疑版本不匹配的告警。

7 通过SLF4J整合日志

    大多数的时候,一个工程会依赖不同的组件,而这些组件又依赖的是日志API,而不是SLF4J。你会发现一个普遍的问题,很多工程同时依赖了JCLjava.util.logginglog4jSLF4J。然后就很期望通过一个单一的途径整合日志。SLF4J通过为JCLjava.util.logginglog4j提供桥模块满足了这个普遍的使用场景。了解更多详细的信息,请参考“桥接传统API

映射诊断上下文支持(MDC)

    映射诊断上下文(Mapped Diagnostic Context)本质上是由日志框架维护的一个映射表map。在映射表中,应用程序提供了键值对,这些键值对可以被掺入到日志框架的日志消息中。MDC数据在过滤消息和触发特定的工作上也是很有用的。

    SLF4J支持MDC。如果底层的日志框架支持MDC功能,那么SLF4J将代理底层框架的MDC。记住,这时只有log4jlogback提供了MDC功能。如果底层的日志框架不支持MDC,例如java.util.logging,那么SLF4J仍然存储MDC数据,但是其中的额信息需要由自定义的用户代码获取。

    这样,作为SLF4J用户,你可以充分发挥在log4jlogback中存在的MDC信息的优势,但是不要强制这些日志框架依赖于用户。

    关于MDC更多的信息,请参看logback手册的关于MDC的章节。

总结

有点

描述

在部署时选择日志框架

通过在类路径中插入合适的jar(绑定),日志框架可以在部署时插入

Fail-fast机制

由于JVM加载类的方式,框架绑定会在很早的时候自动验证。如果SLF4J在类路径中找不到绑定,它就会发出一个单一的告警消息。默认情况下,绑定是没有操作实现NOP

提供流行的日志框架的绑定

SLF4J支持流行的日志框架,即log4jjava.util.loggingsimple loggingNOPlogback工程原生支持SLF4J

桥接传统日志API

SLF4J之上实现JCL,即jcl-over-slf4j.jar,将允许你的工程迁移到SLF4J,而不会破坏使用JCL的已有软件的兼容性。类似的,log4j-over-slf4j.jarjul-to-slf4j模块将分别允许你将log4jjava.util.logging重定向到SLF4J。参考桥接传统API以了解更多详细信息。

迁移源代码

Slf4j迁移器实用工具可以帮助你把代码迁移到使用SLF4J

支持参数化的日志消息

所有的SLF4J绑定支持参数化的日志消息,大大提高了性能。

 

原创粉丝点击