JAVA日誌框架概述

        日誌用來記錄應用的運行狀態以及一些關鍵業務信息,其重要性不言而喻,一般咱們藉助於現有的日誌框架完成日誌輸出。目前開源的日誌框架不少,常見的有log4j、logback等,有時候咱們還會碰到諸如common-logging、slf4j這些名詞,這些框架有什麼做用?它們之間有什麼聯繫?在搭建應用時該如何選擇合適的日誌框架?對於這些問題,將會在本文中作出解釋。

1、日誌門面與日誌組件

        在上面提到的log4j、logback、common-logging、slf4j中,包含了2類框架,其中一類是具體用來輸出日誌的框架,log4j和logback屬於此類,咱們將他們稱爲「日誌組件」;另兩個common-logging、slf4j被歸爲「日誌門面」,或叫作「日誌接口」。
        簡單來講,能夠按照面向接口編程的思想來理解這2種組件,「日誌門面」提供了標準的日誌輸出API,其底層如何實現,或者說採用什麼日誌組件,由開發者進行選擇。固然,選擇的日誌組件必須實現了對應「日誌門面」的接口。

1.1.log4j與logback

        log4j隸屬於apache,其包含一個升級產品(log4j2),是目前流行的日誌組件之一。logback則是近些年來纔開始流行,因爲其在性能上PK掉了log4j,所以愈來愈多的項目開始使用logback。另外JAVA的官方類庫也提供了日誌組件,即JAVA UTIL LOGGING(下文簡稱JUL),這裏咱們不作重點討論。
        下面直接引用一段話來表述log4j和logback的性能差距:
某些關鍵操做,好比斷定是否記錄一條日誌語句的操做,其性能獲得了顯著的提升。這個操做在LogBack中須要3納秒,而在Log4J中則須要30納秒。 
LogBack建立記錄器(logger)的速度也更快:13微秒,而在Log4J中須要23微秒。更重要的是,它獲取已存在的記錄器只需94納秒,而 Log4J須要2234納秒,時間減小到了1/23。跟JUL相比的性能提升也是顯著的。
另外,LOGBack的全部文檔是全面免費提供的,不象Log4J那樣只提供部分免費文檔而須要用戶去購買付費文檔。

1.2.common-logging與slf4j

        前文提到,這2個框架均爲日誌門面,但common-logging(下文簡稱JCL)隸屬於apache陣營,而slf4j與logback爲同一做者。而且這兩個框架與底層日誌組件的綁定機制也不相同:
  • common-logging經過動態查找的機制,在程序運行時自動找出真正使用的日誌庫。因爲它使用了ClassLoader尋找和載入底層的日誌庫,致使了像OSGI這樣的框架沒法正常工做,由於OSGI不一樣的插件使用本身ClassLoader。
  • slf4j編譯時靜態綁定真正的Log庫,所以能夠在OSGI中使用。

2、如何集成slf4j

        在第一節中,咱們解釋了日誌組件和日誌門面的概念,同時提到了slf4j的優越性,接下來咱們將討論如何將slf4j與log4j、logback進行集成,以及如何在一個已經使用了common-logging、jul的遺留系統上無縫集成slf4j。

2.1.基本集成

        若是是一個新系統,或者你想對遺留系統的日誌框架作一個完整的替換,能夠引入以下依賴快速集成:
<!-- 日誌組件log4j與slf4j的集成依賴 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.25</version>
</dependency><!-- 日誌組件logback與slf4j的集成依賴 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.7.25</version>
</dependency><!-- 日誌組件jul與slf4j的集成依賴 -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jdk14</artifactId>
    <version>1.7.25</version>
</dependency><!-- 日誌門面jcl與slf4j的集成依賴,將全部slf4j日誌委派給jcl -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-jcl</artifactId>
    <version>1.7.25</version>
</dependency>

2.2.使用橋接器

        在實際的應用中,咱們會碰到不一樣的組件使用不一樣日誌框架的狀況, 例如Spring Framework使用的是經過日誌門面commons-logging輸出日誌,XSocket依賴的則是JUL。咱們想統一它們的日誌輸出方式以便於管理。
        slf4j提供了現成的解決方案,那即是「橋接器」,它的功能是將這些不一樣形式的日誌打印輸出重定向到slf4j,而後slf4j又會根據綁定器把日誌交給具體的日誌實現工具。下面給出一個經常使用的應用橋接配置方案:
<!-- JUL橋接器,將jul的日誌輸出重定向到slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jul-to-slf4j</artifactId>
</dependency>
<!-- JCL橋接器,將commos-logging的日誌輸出重定向到slf4j -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
</dependency>
<!--log4j橋接器,將log4j的日誌輸出重定向到slf4j  -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>log4j-over-slf4j</artifactId>
</dependency>
<!-- 日誌組件logback與slf4j的集成依賴,各橋接器的重定向最終流向logback -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
</dependency>
        將上述依賴轉換爲流程圖:
        另外,使用橋接器的時候,咱們須要注意避免與2.1中的jar包混淆使用,致使日誌流死循環:
條件 緣由
log4j-over-slf4j.jar和slf4j-log4j12.jar同時存在 slf4j-log4j12.jar會將全部日誌調用委託給log4j,而log4j-over-slf4j.jar又將全部對log4j的調用委託給相應的slf4j,二者造成了一個死循環.
jul-to-slf4j.jar和slf4j-jdk14.jar同時存在 slf4j-jdk14.jar會將全部日誌調用委託給jdk的log,而jul-to-slf4j.jar又將全部對jul-api的調用委託給相應的slf4j,二者造成了一個死循環。
相關文章
相關標籤/搜索