Java常用的日誌框架對比和分析
前言
作為一名資深的開發人員,對於日誌記錄框架一定不會很陌生。而且幾乎在所有應用裡面,一定會用到各種各樣的
日誌框架用來記錄程式的執行資訊。而對於一個成熟的java應用,這個是必不可少的。在開發和除錯階段,日誌可以幫助我們更快的定位問題;而在應用的運維過程中,日誌系統又可以幫助我們記錄大部分的異常資訊,通常很多企業會通過收集日誌資訊來對系統的執行狀態進行實時監控預警。那麼,你對日誌框架到底有多瞭解呢?
常用的日誌框架
Log4j
Log4j是apache下一個功能非常豐富的java日誌庫實現,Log4j應該是出現比較早而且最受歡迎的java日誌組
件,它是基於java的開源的日誌元件。Log4j的功能非常強大,通過Log4j可以把日誌輸出到控制檯、檔案、使用者介面。也可以輸出到作業系統的事件記錄器和一些系統常駐程序。值得一提的是:Log4j可以允許你非常便捷地自定義日誌格式和日誌等級,可以幫助開發人員全方位的掌控自己的日誌資訊
Log4j2
Log4j2是Log4j1的升級版本。Log4j2基本上把Log4j版本的核心全部重構掉了,而且基於Log4j做了很多優化和改變
Logback
Logback是由Log4j創始人設計的另一個開源日誌元件,也是作為Log4j的替代者出現的。而且官方是建議和
Slf4j一起使用,你們一定不知道Logback、slf4j、Log4j都是出自同一個人吧。 Logback是在Log4j的基礎上做的改進版本,而Slf4j又是同一個人設計的,所以預設就對Slf4j無縫結合。
JDK-Logging
Jdk1.4版本以後開始提供的一個自帶的日誌庫實現
統一日誌模組
目前市面上有兩個用得比較廣泛的統一日誌規範介面,分別是
SLF4j
SLF4j(Simple Logging Facade For Java)是基於API的java日誌框架,SLF4j提供了一個簡單統一的日
志記錄介面,開發者在配置和部署時,只需要實現這個介面就可以實現日誌功能。可以說,它並不是一個具體的日誌解決方案,它只是服務於各種各樣的日誌系統,允許終端使用者在部署應用上使用自己常用的日誌系統
Commons-Logging
Common-logging 為眾多具體的日誌實現庫提供了一個統一的介面,和SLF4j的作用類似,它允許在執行時繫結任意的日誌庫;
這裡其實有個小故事,當年apache說服Log4j以及其他的日誌框架按照Commons-Logging的標準來編寫,但是由於Commons-Logging的類載入有點問題,實現起來不友好。因此Log4j的作者就創作了Slf4j,也因此與Commons-Logging兩份天下
圖說幾個日誌框架的關係
各個日誌的功能演示
各個日誌模組的功能演示和配置說明,我就不做多說了,網上搜索下一抓一大把,都講得很詳細。
slf4j和各個日誌框架整合的原理
這裡要重點說明一個東西,就是slf4j通過一個非常有趣而且很牛的設計,把各個日誌框架去整合進來。
如果你們去看slf4j的原始碼,在LoggerFactory.java裡面有一個這樣的靜態全域性變數
private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
有一段核心程式碼
static Set<URL> findPossibleStaticLoggerBinderPathSet() {
LinkedHashSet staticLoggerBinderPathSet = new LinkedHashSet();
try {
ClassLoader ioe = LoggerFactory.class.getClassLoader();
Enumeration paths;
if(ioe == null) {
paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
} else {
paths = ioe.getResources(STATIC_LOGGER_BINDER_PATH);
}
while(paths.hasMoreElements()) {
URL path = (URL)paths.nextElement();
staticLoggerBinderPathSet.add(path);
}
} catch (IOException var4) {
Util.report("Error getting resources from path", var4);
}
return staticLoggerBinderPathSet;
}
大家對ClassLoader機制瞭解的同學,這段程式碼看起來就非常容易懂了,通過ClassLoader去載入classpath下所有存在StaticLoggerBinder.class的檔案。找到這個檔案以後加到一個集合裡面。通過載入到對應jar中的StaticLoggerBinder。來獲取例項。
public static ILoggerFactory getILoggerFactory() {
if (INITIALIZATION_STATE == UNINITIALIZED) {
synchronized (LoggerFactory.class) {
if (INITIALIZATION_STATE == UNINITIALIZED) {
INITIALIZATION_STATE = ONGOING_INITIALIZATION;
performInitialization();
}
}
}
switch (INITIALIZATION_STATE) {
case SUCCESSFUL_INITIALIZATION:
return StaticLoggerBinder.getSingleton().getLoggerFactory();
case NOP_FALLBACK_INITIALIZATION:
return NOP_FALLBACK_FACTORY;
case FAILED_INITIALIZATION:
throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
case ONGOING_INITIALIZATION:
// support re-entrant behavior.
// See also http://jira.qos.ch/browse/SLF4J-97
return SUBST_FACTORY;
}
throw new IllegalStateException("Unreachable code");
}
在這段程式碼裡面,可以看到有一個StaticLoggerBinder.getSingleton().getLoggerFactory()
這個就是在第三方的整合包中返回的例項。這個就是slf4j裡面比較核心的一塊