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

log4j 以及 logback, slf4j 官网

日志框架的困惑

作为一个正常的项目,是必须有日志框架的存在的,没有日志,很难追踪一些奇奇怪怪的系统问题。
但是,我们经常在项目的依赖中,见到奇奇怪怪 slf4j-api,slf4j-log4j12,log4j-over-slf4j,log4j,log4j-core,logback,这些这么多,每次配置日志要导入这些包。
难免有些疑惑,为啥导入这么多依赖,有时候按照习惯导入的依赖,引入之后日志框架报错,多重绑定等等问题。
以及,配置文件有log4j.xml ,有log4j2.xml,有logging.properties,有logback.xml,log4j.properties,完全不知道怎么对应。

例如一个经常见到的,多重SLF4j绑定的错误,在SpringBoot项目中报错是无法启动的。

SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/C:/project/org.slf4j/slf4j-log4j12/1.7.10/xxx/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/C:/project/ch.qos.logback/logback-classic/1.1.2/xxx/logback-classic-1.1.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]

jul

JUL就是 JDK的LOG,(java.util.logging or JUL for short),这个就是JDK原生的了,仅仅满足最基本最原始的日志需求。

SLF4j

slf4j只是一个日志标准,并不是日志系统的具体实现。理解这句话非常重要,slf4j只做两件事情:

提供日志接口
提供获取具体日志对象的方法
slf4j-simple、logback都是slf4j的具体实现,log4j并不直接实现slf4j,但是有专门的一层桥接slf4j-log4j12来实现slf4j。

也就是说,我们可以推定,现在的稍微新一点的系统中一般都会有slf4j-api,看名字就知道这个依赖是少不了的。我们不用担心他导致冲突。

log4j

log4j是一个用Java编写的可靠,快速和灵活的日志框架(API),它在Apache软件许可下发布。

Log4j已经被移植到了C,C++,C#,Perl,Python和Ruby等语言中。

Log4j是高度可配置的,并可通过在运行时的外部文件配置。它根据记录的优先级别,并提供机制,以指示记录信息到许多的目的地,诸如:数据库,文件,控制台,UNIX系统日志等。
Log4j中有三个主要组成部分:loggers: 负责捕获记录信息。appenders : 负责发布日志信息,以不同的首选目的地。layouts: 负责格式化不同风格的日志信息。

logback

logback 是log4j创始人写的,性能比log4j要好,是目前最好,最推荐使用的框架,目前主要分为3个模块

logback-core:核心代码模块
logback-classic:log4j的一个改良版本,同时实现了slf4j的接口,这样你如果之后要切换其他日志组件也是一件很容易的事
logback-access:访问模块与Servlet容器集成提供通过Http来访问日志的功能。

这里就不介绍 logback 为什么能取代log4j了

jcl

JCL,全称为"Jakarta Commons Logging",也可称为"Apache Commons Logging"。

JCL这个日志框架跟Log4J,Java Logging API等日志框架不同。

JCL采用了设计模式中的“适配器模式”,它对外提供统一的接口,然后在适配类中将对日志的操作委托给具体的日志框架,比如Log4J,Java Logging API等。

可见,他是和 slf4j 差不多的,但是需要适配的。

SLF4j 的转换关系以及工作原理

这里也不做过多介绍,看这个官网的图,一目了然
绑定细节

另外,桥接适配的图:

这里做一下简短的说明,
slf4j-log4j12 是用log4j实现的slf4j,会强制将SLF4j的请求转发为log4j的实现,配置文件对应log4j.xml。
log4j-over-slf4j 是桥接所有log4j的API,转向 SLF4j的实现。如果这两者同时出现,则导致互相调用导致无限循环。他的作用是解决 logback和log4j共存的问题,有些依赖框架使用了log4j,这可以使得框架的日志能够被转发到logback中。

The presence of slf4j-log4j12.jar, that is the log4j binding for SLF4J, will force all SLF4J calls to be delegated to log4j. The presence of log4j-over-slf4j.jar will in turn delegate all log4j API calls to their SLF4J equivalents. If both are present simultaneously, slf4j calls will be delegated to log4j, and log4j calls redirected to SLF4j, resulting in an endless loop.

同理,jul-over-slf4j,jcl-over-slf4j,都是这个作用,将jul 以及 jcl 适配到 slf4j的实现类中。(通常是 logback,over 的含义就是 the underlying,jcl 门面,底层实现为slf4j的实现 )

log4j , log4j-core, logback的配置文件对应关系

log4j 这个一般是 1.x的也就是 对应配置文件为 log4j.xml
log4j-core 这个是 2.x 的log4j,因为log4j已经过时。而他对应 log4j2.xml
slf4j-log4j12 这个实际上对应 log4j 1.2,他的配置文件是 log4j.xml
logback-classic和logback-core 就是 logback.xml

注意 log4j的配置文件语法,和 log4j2,以及logback这三者的语法均不相同。
相关的语法,不建议在博客中复制,直接查看apache log4j ,以及 qos.ch 官网(包含 slf4j ,log4j,logback)的配置文件示例。

理由如下:
log4j的配置文件:
appender里面的是 level,而root里面是priority。很多博客给出的是错误的。

posted @ 2018-12-05 15:44  一杯半盏  阅读(1260)  评论(0编辑  收藏  举报