JAVA日志在初期可能官方并没有提供很好且实用的规范,导致各公司或OSS作者选择自行造轮子,这也导致了目前初学者觉得市面上 Java 日志库繁杂的局面。
现在市面流行以 slf4j(Simple Logging Facade for Java)做日志接口,基于门面模式的思想,开发者只需熟悉/使用 slf4j API 即可,而具体实现则是可更替的。
以 slf4j 的概念,共可划分为以下4种库:
日志接口层 | slf4j-api,common-logging |
日志实现层 | JUL(java.util.logging) log4j logback slf4j-simple,slf4j-nop |
绑定适配(adaptation)层 | slf4j-jcl slf4j-jdk14 slf4j-log412 |
桥接(bridge)层 | jcl-over-slf4j jul-to-slf4j log4j-over-slf4j |
slf4j 几种流程示意图:Bridging legacy APIs
接口层的作用上面已经说了
以 SLF4J 为例,它并非日志的实现(当然也没有实现的概念,因为没有标准),而是各种日志框架(java.util.logging,logbacak,log4j)的简单门面(facade,门面设计模式)或抽象接口,允许用户在部署时选择期望的日志框架实现。
顾名思义,各种可用日志框架
需注意:与JDBC这种官方接口规范不同,这些日志框架(如 log4j)并不一定实现自接口层 ,因为 slf4j接口 也只是第三方规范而已。
但有些日志框架本身就是接口层框架的实现,比如 logback 本地实现了 slf4j
为了让非本地实现 slf4j 的框架(如 log4j)也能在 slf4j API 下工作,据 sfl4j 版本不同有两种实现方式:
为了不修改已有项目代码或想在项目中延用旧日志框架,同时又想让slf4j统一处理,可引入桥接包(如 log4j-over-slf4j.jar
)替换原有的日志框架(log4j.jar
),以此将日志重定向委托给 SLF4j
注意:桥接层与实现层不能为同一个日志框架,否则将造成无限循环,这也很容易理解。例如:jcl-over-slf4j.jar
与 slf4j-jcl.jar
不能同时使用
以下仅简略概述,有个大概印象即可(该篇目不意在深入某具体框架):
Log4j
Apache 的开源日志框架,名称含义 "Log for Java"
JUL(java.util.logging)
java.util.logging,由 JDK1.4 引入
JCL(Jakarta Commons Logging)
也叫 "Apache Commons Logging",也等同于常说的 common-logging,是为解决市面上不同日志库而最早诞生的日志接口标准。
JCL 只提供日志接口,具体实现则是在"运行时动态寻找",其内部也有个 Simple logger 简单实现但功能很弱,因此仍会看到很多程序使用 JCL + log4j 这种搭配。
动态查找原理概述:
但随着程序规模越来越庞大时,JCL动态绑定并不总是能成功,这也是 SLF4J 诞生原因之一。
SLF4J
为改进 common-logging 而生的日志接口
详见 SLF4J 快速入门 / 原理探究
LogBack
log4j 创始人设计的又一开源日志组件,通用、可靠、快速灵活 声称有极佳的性能。
其一大特色是,其在 logback-classic 中本地(native)实现了 SLF4J API。
当前分为三个模块:
java.util.logging.LogManager
上的 @since 1.4
可知nop
表示 no-operation,即无操作空实现。参考:
- java日志组件介绍(jcl,jul,slf4j,logback很全,很透,看了一遍差不多就明白了
- 日志系列好文 https://www.cnblogs.com/xuningfans/p/12164734.html
- http://www.slf4j.org/