Java 日誌框架概述(slf4j / log4j / JUL / Common-logging(JCL) / logback)
一、簡介
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 版本不同有兩種實現方式:
- (1.8 以前)靜態綁定
- (1.8 以後)基於Java6 Java SPI (Service Provider Interface) 機制
無論那種哪種,都是需要引入這樣一種適配器包來實現
橋接層
為了不修改已有項目程式碼或想在項目中延用舊日誌框架,同時又想讓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 這種搭配。
動態查找原理概述:- 首先,尋找 org.apache.commons.logging.LogFactory 的屬性配置
- 否則,則利用 SPI 機制
- 否則,讀取類路徑下 commons-logging.properties 的配置
- 否則,若存在 log4j,默認使用 log4j
- 否則,使用 JDK1.4 Logger
- 否則,使用內部的 SimpleLog
但隨著程式規模越來越龐大時,JCL動態綁定並不總是能成功,這也是 SLF4J 誕生原因之一。
-
SLF4J
為改進 common-logging 而生的日誌介面
詳見 SLF4J 快速入門 / 原理探究 -
LogBack
log4j 創始人設計的又一開源日誌組件,通用、可靠、快速靈活 聲稱有極佳的性能。
其一大特色是,其在 logback-classic 中本地(native)實現了 SLF4J API。
當前分為三個模組:- logback-core:其他倆模組基礎模組
- logback-classic:日誌模組,完整實現了 SLF4J API
- logback-access:配合Servlet容器,提供 http 訪問日誌功能
四、延申
- slf4j 制定了日誌標準當然有優點,但 slf4j 為什麼會成為標準,而非 jul 來指定標準(就像 JDBC 一樣)?
答:可參考此處提到的恩怨情仇 //juejin.cn/post/6844904037641355271 - 一些jul相關包名上的 jdk14,指的是 JDK1.4(按現在版本規範來說是 JAVA 4),而不是 JAVA 14
可以查看java.util.logging.LogManager
上的@since 1.4
可知 - 一些包上的
nop
表示 no-operation,即無操作空實現。
參考:
– java日誌組件介紹(jcl,jul,slf4j,logback很全,很透,看了一遍差不多就明白了
– 日誌系列好文 //www.cnblogs.com/xuningfans/p/12164734.html
– //www.slf4j.org/