2015第30週四Java日誌組件

Java 日誌 API

從功能上來講,日誌 API 自己所需求的功能很是簡單,只須要可以記錄一段文本便可。API 的使用者在須要進行記錄時,根據當前的上下文信息構造出相應的文本信息,調用 API 完成記錄。通常來講,日誌 API 由下面幾個部分組成:java

  • 記錄器(Logger):日誌 API 的使用者經過記錄器來發出日誌記錄請求,並提供日誌的內容。在記錄日誌時,須要指定日誌的嚴重性級別。當 程序中須要記錄日誌時,首先須要獲取一個日誌記錄器對象。通常的日誌記錄 API 都提供相應的工廠方法來建立記錄器對象。每一個記錄器對象都是有名稱的。通常的作法是使用當前的 Java 類的名稱或所在包的名稱做爲記錄器對象的名稱。
  • 格式化器(Formatter):對記錄器所記錄的文本進行格式化,並添加額外的元數據。實際記錄的日誌中除了使用記錄器對象時提供的消息以外,還包括一些元數據。這些元數據由日誌記錄框架來提供。經常使用的信息包括記錄器的名稱、時間戳、線程名等。格式化器用來肯定全部這些信息在日誌記錄中的展現方式。不一樣的日誌記錄實現提供各自默認的格式化方式和自定義支持。
  • 處理器(Handler):把通過格式化以後的日誌記錄輸出到不一樣的地方。常見的日誌輸出目標包括控制檯、文件和數據庫等。

Java 日誌封裝 API

封裝庫中一開始以 Apache Commons Logging 框架最爲流行,如今比較流行的是 SLF4J。這樣封裝庫的 API 都比較簡單,只是在日誌記錄庫的 API 基礎上作了一層簡單的封裝,屏蔽不一樣實現之間的區別。因爲日誌記錄實現所提供的 API 大體上比較類似,封裝庫的做用更多的是達到語法上的一致性。數據庫

在 Apache Commons Logging 庫中,核心的 API 是 org.apache.commons.logging.LogFactory 類和 org.apache.commons.logging.Log 接口。LogFactory 類提供了工廠方法用來建立 Log 接口的實現對象。好比 LogFactory.getLog 能夠根據 Java 類或名稱來建立 Log 接口的實現對象。Log 接口中爲 6 個不一樣的嚴重性級別分別定義了一組方法。好比對 DEBUG 級別,定義了 isDebugEnabled()、debug(Object message) 和 debug(Object message, Throwable t) 三個方法。從這個層次來講,Log 接口簡化了對於日誌記錄器的使用。apache

SLF4J 庫的使用方式與 Apache Commons Logging 庫比較相似。SLF4J 庫中核心的 API 是提供工廠方法的 org.slf4j.LoggerFactory 類和記錄日誌的 org.slf4j.Logger 接口。經過 LoggerFactory 類的 getLogger 方法來獲取日誌記錄器對象。與 Apache Commons Logging 庫中的 Log 接口相似,Logger 接口中的方法也是按照不一樣的嚴重性級別來進行分組的。Logger 接口中有一樣 isDebugEnabled 方法。不過 Logger 接口中發出日誌記錄請求的 debug 等方法使用 String 類型來表示消息,同時可使用包含參數的消息。編程

slf4j 與 common-logging 比較

common-logging經過動態查找的機制,在程序運行時自動找出真正使用的日誌庫。因爲它使用了ClassLoader尋找和載入底層的日誌庫, 致使了象OSGI這樣的框架沒法正常工做,由於OSGI的不一樣的插件使用本身的ClassLoader。 OSGI的這種機制保證了插件互相獨立,然而卻使Apache Common-Logging沒法工做。

slf4j在編譯時靜態綁定真正的Log庫,所以能夠再OSGI中使用。另外,SLF4J 支持參數化的log字符串,避免了以前爲了減小字符串拼接的性能損耗而不得不寫的if(logger.isDebugEnable()),如今你能夠直接寫:logger.debug(「current user is: {}」, user)。拼裝消息被推遲到了它可以肯定是否是要顯示這條消息的時候,可是獲取參數的代價並無倖免。
 
日誌框架實現

Log4j

Apache的一個開放源代碼項目,經過使用Log4j,咱們能夠控制日誌信息輸送的目的地是控制檯、文件、GUI組件、甚至是套接口服務 器、NT的事件記錄器、UNIX Syslog守護進程等;用戶也能夠控制每一條日誌的輸出格式;經過定義每一條日誌信息的級別,用戶可以更加細緻地控制日誌的生成過程。這些能夠經過一個 配置文件來靈活地進行配置,而不須要修改程序代碼。

LogBack

Logback是由log4j創始人設計的又一個開源日記組件。logback當前分紅三個模塊:logback-core,logback- classic和logback-access。logback-core是其它兩個模塊的基礎模塊。logback-classic是log4j的一個 改良版本。此外logback-classic完整實現SLF4J API使你能夠很方便地更換成其它日記系統如log4j或JDK14 Logging。logback-access訪問模塊與Servlet容器集成提供經過Http來訪問日記的功能。 

Log4j 與 LogBack 比較

LogBack做爲一個通用可靠、快速靈活的日誌框架,將做爲Log4j的替代和SLF4J組成新的日誌系統的完整實現。LOGBack聲稱具備極佳的性能,「 某些關鍵操做,好比斷定是否記錄一條日誌語句的操做,其性能獲得了顯著的提升。這個操做在LogBack中須要3納秒,而在Log4J中則須要30納秒。 LogBack建立記錄器(logger)的速度也更快:13微秒,而在Log4J中須要23微秒。更重要的是,它獲取已存在的記錄器只需94納秒,而 Log4J須要2234納秒,時間減小到了1/23。跟JUL相比的性能提升也是顯著的」。 另外,LOGBack的全部文檔是全面免費提供的,不象Log4J那樣只提供部分免費文檔而須要用戶去購買付費文檔。 
 
總結
接口:將全部日誌實現適配到了一塊兒,用統一的接口調用。 
實現:目前主流的日誌實現 
舊日誌到slf4j的適配器:若是使用了slf4j,可是隻想用一種實現,想把log4j的日誌體系也從logback輸出,這個是頗有用的。 
slf4j到實現的適配器:若是想制定slf4j的具體實現,須要這些包。 

slf4J與舊日誌框架的關係 
slf4j等於commons-logging,是各類日誌實現的通用入口,會根據classpath中存在下面哪個Jar來決定具體的日誌實現庫。 
logback-classic(默認的logback實現) 
slf4j-jcl.jar(apache commons logging) 
slf4j-logj12.jar(log4j 1.2.4) 
slf4j-jdk14(java.util.logging) 
將全部使用舊式日誌API的第三方類庫或舊代碼的日誌調用轉到slfj 
jcl-over-slf4j.jar/jcl104-over-slf4j:apache commons logging 1.1.1/1.0.4,直接替換便可。 
log4j-over-slf4j.jar:log4j,直接替換便可。 
jul-to-slf4j:jdk logging,須要在程序開始時調用SLF4JBridgeHandler.install()來註冊listener參考JulOverSlf4jProcessor,可在applicationContext.xml中定義該bean來實現初始化。注意原有的log4j.properites將失效,logback網站上提供轉換器,支持從log4j.properties 轉換到logback.xml 。 
 

日誌組件相關歷史

Java 界裏有許多實現日誌功能的工具,最先獲得普遍使用的是 log4j,許多應用程序的日誌部分都交給了 log4j,不過做爲組件開發者,他們但願本身的組件沒關係緊依賴某一個工具,畢竟在同一個時候還有不少其餘不少日誌工具,假如一個應用程序用到了兩個組件,剛好兩個組件使用不一樣的日誌工具,那麼應用程序就會有兩份日誌輸出了。

爲了解決這個問題,Apache Commons Logging (以前叫 Jakarta Commons Logging,JCL)粉墨登場,JCL 只提供 log 接口,具體的實現則在運行時動態尋找。這樣一來組件開發者只須要針對 JCL 接口開發,而調用組件的應用程序則能夠在運行時搭配本身喜愛的日誌實踐工具。

因此即便到如今你仍會看到不少程序應用 JCL + log4j 這種搭配,不過當程序規模愈來愈龐大時,JCL的動態綁定並非總能成功,具體緣由你們能夠 Google 一下,這裏就再也不贅述了。解決方法之一就是在程序部署時靜態綁定指定的日誌工具,這就是 SLF4J 產生的緣由。

跟 JCL 同樣,SLF4J 也是隻提供 log 接口,具體的實現是在打包應用程序時所放入的綁定器(名字爲 slf4j-XXX-version.jar)來決定,XXX 能夠是 log4j12, jdk14, jcl, nop 等,他們實現了跟具體日誌工具(好比 log4j)的綁定及代理工做。舉個例子:若是一個程序但願用 log4j 日誌工具,那麼程序只需針對 slf4j-api 接口編程,而後在打包時再放入 slf4j-log4j12-version.jar 和 log4j.jar 就能夠了。

如今還有一個問題,假如你正在開發應用程序所調用的組件當中已經使用了 JCL 的,還有一些組建可能直接調用了 java.util.logging,這時你須要一個橋接器(名字爲 XXX-over-slf4j.jar)把他們的日誌輸出重定向到 SLF4J,所謂的橋接器就是一個假的日誌實現工具,好比當你把 jcl-over-slf4j.jar 放到 CLASS_PATH 時,即便某個組件本來是經過 JCL 輸出日誌的,如今卻會被 jcl-over-slf4j 「騙到」SLF4J 裏,而後 SLF4J 又會根據綁定器把日誌交給具體的日誌實現工具。過程以下

Component
|
| log to Apache Commons Logging
V
jcl-over-slf4j.jar --- (redirect) ---> SLF4j ---> slf4j-log4j12-version.jar ---> log4j.jar ---> 輸出日誌

看到上面的流程圖可能會發現一個有趣的問題,假如在 CLASS_PATH 裏同時放置 log4j-over-slf4j.jar 和 slf4j-log4j12-version.jar 會發生什麼狀況呢?沒錯,日誌會被踢來踢去,最終進入死循環。

因此使用 SLF4J 的比較典型搭配就是把 slf4j-api、JCL 橋接器、java.util.logging(JUL)橋接器、log4j 綁定器、log4j 這5個 jar 放置在 CLASS_PATH 裏。

不過並非全部APP容器都是使用 log4j 的,好比 Google AppEngine 它使用的是 java.util.logging(JUL),這時應用 SLF4J 的搭配就變成 slf4j-api、JCL橋接器、logj4橋接器、JUL綁定器這4個 jar 放置在 WEB-INF/lib 裏。
 
http://blog.jobbole.com/51155/
http://phl.iteye.com/blog/2021461
http://blog.csdn.net/yycdaizi/article/details/8276265
相關文章
相關標籤/搜索