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包中。
以上概念的关系如下图:
图1 SLF4J概念关系
2 使用
2.1 一般流程
使用SLF4J一般包含3个步骤:
- 添加组件依赖:给项目添加SLF4J API,SLF4J binding 和 日志库组件依赖。最多只能添加一个SLF4J binding,若添加多个,则SLF4J会给出警告,并选择使用一个SLF4J binding。若不添加SLF4J binding,则SLF4J会给出警告,并忽略所有的记录日志语句。注意,SLF4J API 与 SLF4J binding 的版本必须匹配,SLF4J在初始化时(首次调用 org.slf4j.LoggerFactory.getILoggerFactory 方法会触发SLF4J初始化)会检查二者的匹配情况,若发现二者不匹配,则会发出警告。
- 编辑日志库配置文件:针对具体日志库,在特定位置创建一个日志配置文件,并编辑文件内容。
- 编写代码:使用SLF4J API编程。
2.2 示例
下面以一个使用log4j 2日志库的Maven终端项目(既不是库、框架、中间件等类型项目,也不会被其他项目引用的项目)为例,演示SLF4J的使用。
1) 添加组件依赖
下面的代码块是项目的pom.xml文件的一部分,在该代码块中,我们只指定了SLF4J binding 依赖 log4j-slf4j-impl,而没有指定 SLF4J API 和 日志库依赖,这是因为Maven会通过 log4j-slf4j-impl 组件的依赖自动解决依赖。
2) 编辑日志库配置文件<!-- SLF4J binding -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.14.1</version>
</dependency>
在 src/main/resources 目录下创建log4j 2的配置文件 log4j2.xml,编辑内容如下:
3) 编写代码<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="debug">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
首先用 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);
public static void main(String[] args) {
logger.info("classpath={}", System.getProperty("java.class.path"));
}
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