1 简介

SLF4J(Simple Logging Facade for Java)为各种日志库(java.util.logging, logback 和 log4j 等)提供了一个统一API,应用通过SLF4J API进行日志操作,而SLF4J API之下真正实现日志功能的可以是任意日志库。在代码层面,应用只与SLF4J API关联,不与SLF4J API之下的日志库关联。

概念:

  • 应用:使用SLF4J API进行日志操作的程序
  • SLF4J API:给应用提供的日志编程接口
  • SLF4J binding:SLF4J API和日志库的连接器
  • 日志库:真正实现日志功能的程序库

大体上,SLF4J API,SLF4J binding 和 日志库各自对应1个jar包。某些SLF4J binding和日志库位于同一个jar包中。
以上概念的关系如下图:
image.png
图1 SLF4J概念关系

2 使用

2.1 一般流程

使用SLF4J一般包含3个步骤:

  1. 添加组件依赖:给项目添加SLF4J API,SLF4J binding 和 日志库组件依赖。最多只能添加一个SLF4J binding,若添加多个,则SLF4J会给出警告,并选择使用一个SLF4J binding。若不添加SLF4J binding,则SLF4J会给出警告,并忽略所有的记录日志语句。注意,SLF4J API 与 SLF4J binding 的版本必须匹配,SLF4J在初始化时(首次调用 org.slf4j.LoggerFactory.getILoggerFactory 方法会触发SLF4J初始化)会检查二者的匹配情况,若发现二者不匹配,则会发出警告。
  2. 编辑日志库配置文件:针对具体日志库,在特定位置创建一个日志配置文件,并编辑文件内容。
  3. 编写代码:使用SLF4J API编程。

    2.2 示例

    下面以一个使用log4j 2日志库的Maven终端项目(既不是库、框架、中间件等类型项目,也不会被其他项目引用的项目)为例,演示SLF4J的使用。
    1) 添加组件依赖
    下面的代码块是项目的pom.xml文件的一部分,在该代码块中,我们只指定了SLF4J binding 依赖 log4j-slf4j-impl,而没有指定 SLF4J API 和 日志库依赖,这是因为Maven会通过 log4j-slf4j-impl 组件的依赖自动解决依赖。
    1. <!-- SLF4J binding -->
    2. <dependency>
    3. <groupId>org.apache.logging.log4j</groupId>
    4. <artifactId>log4j-slf4j-impl</artifactId>
    5. <version>2.14.1</version>
    6. </dependency>
    2) 编辑日志库配置文件
    在 src/main/resources 目录下创建log4j 2的配置文件 log4j2.xml,编辑内容如下:
    1. <?xml version="1.0" encoding="UTF-8"?>
    2. <Configuration status="WARN">
    3. <Appenders>
    4. <Console name="Console" target="SYSTEM_OUT">
    5. <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
    6. </Console>
    7. </Appenders>
    8. <Loggers>
    9. <Root level="debug">
    10. <AppenderRef ref="Console"/>
    11. </Root>
    12. </Loggers>
    13. </Configuration>
    3) 编写代码
    首先用 org.slf4j.LoggerFactory.getLogger 方法得到一个 org.slf4j.Logger 实例,然后对该实例调用debug/info/warn/error 等方法记录日志。 ```java package zixiu.learnjava01;

import org.slf4j.Logger; import org.slf4j.LoggerFactory;

public class Slf4jDemo { private static final Logger logger = LoggerFactory.getLogger(Slf4jDemo.class);

  1. public static void main(String[] args) {
  2. logger.info("classpath={}", System.getProperty("java.class.path"));
  3. }

} ```

2.3 库类型项目使用SLF4J

库、框架等类型项目使用SLF4J时,只能指定SLF4J API依赖,不能指定SLF4J binding 和 日志库依赖(具体地讲,不能指定scope=runtime的依赖,但可以指定scope=test的依赖)。若库项目指定了SLF4J binding依赖,依赖该库的项目也依赖该库的SLF4J binding。设想一个项目依赖于库A和库B 2个库,而库A和库B分别依赖于logback 和 log4j 2 的 SLF4J binding,则该项目会依赖2个SLF4J binding,这违背了2.1节说的一个项目最多只能指定1个SLF4J binding的原则。

3 原理

关键:org.slf4j.impl.StaticLoggerBinder 类
TODO

4 参考资料

【SLF4J user manual】 http://www.slf4j.org/manual.html