SLF4J與Logback、Log4j1、Log4j2、JCL、J.U.L是如何關聯使用的

日誌是Java程序員日常開發當中必須要接觸的一個環節。Java的日誌五花八門,有各種各樣的實現,現在梳理一下Java日誌相關的框架,及其使用使用細節。我們在日常使用過程中,主要會接觸到SLF4J、Logback、Log4j1、Log4j2、JCL和J.U.L等日誌框架。

對於日誌框架的最佳實踐,推薦使用使用Log Facade,而不是具體Log Implementation,即在代碼中直接使用 Log4j-API 或者 SLF4J(不推薦繼續使用 JCL)的類,而不推薦使用Log4j1,Log4j2,Logback或者J.U.L的類(配置文件當中配置好即可)。

Log4j-API/Log4j-core類似於SLF4J/Logback,在Log4j2的官方文檔當中宣稱比Logback性能高很多LINK,其實現方案類似於SLF4J/Logback,因此,在這裏主要分析SLF4J與不同的日誌框架的關聯使用情況。

1. SLF4J承接不同的日誌框架(日誌框架—->SLF4J)

官方文檔

當項目是使用多種日誌API時,可以統一適配到SLF4J,中間使用SLF4J或者第三方提供的日誌適配器適配到SLF4J,SLF4J再底層用開發者想用的一個日誌框架來進行日誌系統的實現,從而達到了多種日誌的統一實現。其中的技術實現大體有一下兩種方式:

  • 重寫上游類的實現。比如jcl-over-slf4j和log4j-over-slf4j,爲了承接log4j 1,重寫了log4j 1 的Logger和LogFactory類。
  • 對接上游類的擴展方案。比如jul-to-slf4j和log4j-to-slf4j,爲了承接J.U.L,實現了繼承java.util.logging.Handler的SLF4JBridgeHandler。
適配器名稱 原日框架 提供方 刪除的依賴 實現方式 備註
jcl-over-slf4j apache commons-logging SLF4J API:刪除commons-logging
實現:刪除非SLF4J實現的實現類,如SLF4J採用Logback的實現,那麼就需要刪除Log4j1等實現
jcl-over-slf4j重寫了commons-logging的Log和LogFactory類,做了不同的實現 JCL 是一個Log Facade,只提供 Log API,不提供實現,然後有 Adapter 來使用 Log4j 或者 JUL 作爲Log Implementation,是Ceki Gulcu 認爲 JCL 的 API 設計得不好,容易讓使用者寫出性能有問題的代碼,所以重新設計了SLF4J替代JCL。
jul-to-slf4j java jdk-logging SLF4J API:刪除非SLF4J之外的其他Log Facade jul-to-slf4j 下有 SLF4JBridgeHandler實現,系統啓動的時候調用SLF4JBridgeHandler.removeHandlersForRootLogger();刪除所有的Logger,然後調用SLF4JBridgeHandler.install();裝載上SLF4J JUL是JDK自帶的log功能,雖然是官方自帶的log lib,但是由於性能問題和功能等問題,使用不廣泛
log4j-over-slf4j apache log4j 1 SLF4J API:刪除非SLF4J之外的其他Log Facade
實現:刪除非SLF4J實現的實現類,如SLF4J採用Logback的實現,那麼就需要刪除Log4j1等實現
log4j-over-slf4j 重寫了log4j 1 的Logger和LogFactory類,做了不同的實現 Log4j 在設計上非常優秀,對後續的 Java Log 框架有長久而深遠的影響。Log4j 的短板在於性能,在Logback 和 Log4j2 出來之後,Log4j的使用也減少了
log4j-to-slf4j apache Log4j 2 Log4j 2 API:刪除非SLF4J之外的其他Log Facade
實現:刪除非SLF4J實現的實現類,如SLF4J採用Logback的實現,那麼就需要刪除Log4j2等實現
log4j-to-slf4j 使用OSGI SPI的形式爲org.apache.logging.log4j.spi.Provider提供了SLF4J的實現 Log4j 2的性能很好,是未來之星!官方文檔

2. SLF4J對接不同的日誌框架實現(SLF4J—->日誌框架)

官方文檔

SLF4J適配不同的日誌實現,是通過不同的適配器實現的。

  • 在1.8.0-alpha0以前版本採用實現org.slf4j.impl.StaticLoggerBinder的方式實現,
  • 在1.8.0-alpha0之後的版本採用提供org.slf4j.spi.SLF4JServiceProvider的SPI實現的方式實現。

顯然,第一中方式不夠優雅,所以Ceki Gulcu在2017年3月21日對SFL4J的提交過程當中刪除org.slf4j.impl.StaticLoggerBinder,增加了org.slf4j.spi.SLF4JServiceProvider,將原來的查找實現的方式變成了查找SPI服務的方式,但是最新的SPI方案並沒有做對久的org.slf4j.impl.StaticLoggerBinder方式的兼容,這個動作欠妥的,比如SLF4J與Logback的配合上就有問題,類似的問題會出現在其他日誌實現當中。

SLF4J 1.8.0以前版本 SLF4J 1.8.0以後版本
Logback 1.3.0以前版本 正常使用
Logback 1.3.0以後版本 無法正常使用

log4j-slf4j-impl是的Log4j 2提供的對SLF4J的實現,由於是第三方提供的方案,所以其採用了實現org.slf4j.impl.StaticLoggerBinder的方案進行擴展。

2.1 適配器名稱說明

適配器名稱 目標實現 提供方 備註
slf4j-jdk14 jdk-logging J.U.L SLF4J
logback-classic Logback Logback Logback與SLF4J都是Ceki Gulcu的作品,Logback默認帶SLF4J的適配
slf4j-jcl apache commons-logging SLF4J
slf4j-log4j12 Log4j 1 SLF4J
log4j-slf4j-impl Log4j 2 Log4j 2 官方文檔

3. 圖例

參考:Java 日誌框架解析(上) - 歷史演進

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章