Java日誌那些事

日誌系統的發展

咱們平常接觸到的日誌系統有不少種,log4j,JUL(jdk自帶),logback等,咱們能夠直接根據對象的日誌API進行使用。可是考慮到API各不相同,因此出現了JCL(Jakarta Commons Logging)、slf4j等日誌API框架。日誌API框架只是統一的API,其底層的具體的日誌記錄工做仍是由log4j、JUL、logback等承擔。html

如何選擇和搭配日誌系統

目前來講,新應用使用logback是首選,一些老系統中極可能使用的是log4j等。目前slf4j對logback和log4j都支持,對JCL也提供了橋接方法,將JCL的api轉化slf4j的API。貼一張Webx中的圖足以說明一切
圖片描述java

組裝日誌系統

因爲存在JCL,SLF4j兩大日誌框架,logback、log4j、JUL日誌系統因此理論上有這麼多種日誌系統的搭配。spring

  • JUL
  • log4j
  • logback
  • jcl+log4j
  • slf4j+slf4j-log4j12+log4j
  • slf4j+logback
  • jcl-over-slf4j+slf4j+logback
  • jcl-over-slf4j+slf4j+slf4j-log4j12+log4j

其中slf4j+slf4j-log4j12+log4j、slf4j+logback是主流,推薦使用。apache

常見的日誌包以及輔助包功能介紹

JCL(commons-logging)系列

  • commons-logging apache logging抽象日誌工具,通常搭配log4j1/2使用
  • spring-jcl Spring本身的commons-logging同名類日誌,Spring內部的日誌調用的都是commons-logging包,優先選擇Logj
  • jcl-over-slf4j slf4j提供的commons-logging同名日誌類,經過同名類的方式替換實現方式爲slf4j

SLF4j系列

  • slf4j-api Slf4j提供的日誌抽象接口,不包含實現,具體使用何種日誌實現須要引入對應的實現包
  • slf4j-jdk14 Slfj的jdk日誌實現包
  • slf4j-log4j12 Slf4j的log4j1/2實現包

JUL系列

  • jul-to-slf4j Slf4j提供的jul實現包,經過jul提供的擴展接口,定製slf4j的實現

log4j系列

  • log4j log4j v1版本的包
  • log4j-api log4j v2版本的包
  • log4j-over-slf4j Slf4j提供的log4j v1版本的同名日誌類,經過同名類的方式替換實現方式爲slf4j
  • log4j-to-slf4j log4j v2經過spi機制提供的轉換至slf4j的實現

多種日誌工具共存時的解決方案

當依賴了一些三方庫時,可能會出現多種日誌共存的問題,沒法保證每種日誌抽象庫都使用同樣的實現類,此時須要制定固定的日誌庫。
主流的日誌庫都提供了擴展方式api

JUL(java.util.logging)

經過LogManager.getLogManager().getLogger("").addHandler()方法,能夠添加日誌具體實現
LogManager.getLogManager().getLogger("").addHandler(new SLF4JBridgeHandler());
繼承java.util.logging.Handler 類,在實現中使用具體的Logger庫便可
實現例子:
jul-to-slf4j(https://www.slf4j.org/api/org...mybatis

JCL(org.apache.commons.logging)j

經過指定環境變量LogFactory,org.apache.commons.logging.LogFactory
System.setProperty("org.apache.commons.logging.LogFactory","com.answern.claimv2.framework.log.LogFactoryImplAdapter");
繼承org.apache.commons.logging.LogFactory類,實現本身的LogFactory便可框架

還能夠經過jcl提供的spi機制,實現本身的org.apache.commons.logging.LogFactory
建立META-INF/services/org.apache.commons.logging.LogFactory文件,文件內定義LogFactory的完整類名便可。ide

還有另一種暴力的方式:
不引入commons-logging包,而是建立jcl的一些同名類,在實現中直接使用具體的日誌庫。jcl-over-slf4j(https://mvnrepository.com/art...)就是一個典型的例子.
相同功能的還有spring-jcl(https://mvnrepository.com/art...工具

log4j

log4j提供了java對原生spi機制的支持
創建MEATA-INF/services/org.apache.logging.log4j.spi.Provider文件
繼承org.apache.logging.log4j.spi.Provider類,實現本身的LoggerContextFactory便可
實現例子:
log4j-to-slf4j(https://logging.apache.org/lo...spa

SLFJ4J

slf4j官方介紹了使用方式,經過引入不一樣的jar包來使用具體的日誌庫。
因爲slf4j拆分作的很好,當多種日誌庫共存時,若不引入slf4j-xxx.jar時,不會加載相應的日誌庫。
因此若日誌衝突時,使用slf4j的三方庫只須要include/exclude相應的實現庫便可。
concrete-bindings.png

編寫本身的框架/類庫時該如何選擇日誌庫

因爲日誌庫多種多樣,若是盲目引入jcl或者slf4j時,可能會對具體使用的項目形成影響。因此最合適的方式是內嵌一套日誌抽象,內部動態的去選擇加載哪一個日誌庫。主流的成熟框架都會這麼作,儘量的保持兼容性。

例如spring/mybatis/freemarker/dubbo這些框架,都有一套內嵌的日誌抽象,打印日誌時只須要調用內嵌的日誌便可作到全兼容。

參考

相關文章
相關標籤/搜索