每個Java程序員都知道日誌對於任何一個Java應用程序,尤爲是服務端程序是相當重要的,而不少程序員也已經熟悉各類不一樣的日誌庫如java.util.logging、Apache log4j、logback。但若是你還不知道SLF4J(Simple logging facade for Java)的話,那麼是時候去在你項目中學習使用SLF4J了。
在這篇文章中,咱們將學習爲何使用SLF4J比log4j或者java.util.logging要優秀。自從上次我寫Java程序員的10個日誌技巧已經有一段時間了,我已經不記得我寫的關於日誌的一切了。 html
無論怎樣,讓咱們回到這個話題,SLF4J不一樣於其餘日誌類庫,與其它有很大的不一樣。SLF4J(Simple logging Facade for Java)不是一個真正的日誌實現,而是一個抽象層(abstraction layer),它容許你在後臺使用任意一個日誌類庫。若是是在編寫供內外部均可以使用的API或者通用類庫,那麼你真不會但願使用你類庫的客戶端必須使用你選擇的日誌類庫。 java
若是一個項目已經使用了log4j,而你加載了一個類庫,比方說 Apache Active MQ——它依賴於於另一個日誌類庫logback,那麼你就須要把它也加載進去。但若是Apache Active MQ使用了SLF4J,你能夠繼續使用你的日誌類庫而無語忍受加載和維護一個新的日誌框架的痛苦。 程序員
總的來講,SLF4J使你的代碼獨立於任意一個特定的日誌API,這是一個對於開發API的開發者很好的思想。雖然抽象日誌類庫的思想已經不是新鮮的事物並且Apache commons logging也已經在使用這種思想了,但如今SLF4J正迅速成爲Java世界的日誌標準。讓咱們再看看幾個使用SLF4J而不是log4j、logback或者java.util.logging的理由。 api
SLF4J對比Log4J,logback和java.util.Logging的優點 數組
正如我以前說的,在你的代碼中使用SLF4J寫日誌語句的主要出發點是使得你的程序獨立於任意特定的日誌類庫,依賴於特定類可能須要不一樣與你已有的配置,而且致使更多維護的麻煩。但除此以外,還要一個SLF4J API的特性使得我堅持使用SLF4J而拋棄我長期間鍾愛的Lof4j的理由,是被稱爲佔位符(place holder),在代碼中表示爲「{}」的特性。佔位符是一個很是相似於在String的format()方法中的%s,由於它會在運行時被某個提供的實際字符串所替換。這不只下降了你代碼中字符串鏈接次數,並且還節省了新建的String對象。即便你可能沒須要那些對象,但這個依舊成立,取決於你的生產環境的日誌級別,例如在DEBUG或者INFO級別的字符串鏈接。由於String對象是不可修改的而且它們創建在一個String池中,它們消耗堆內存( heap memory)並且大多數時間他們是不被須要的,例如當你的應用程序在生產環境以ERROR級別運行時候,一個String使用在DEBUG語句就是不被須要的。經過使用SLF4J,你能夠在運行時延遲字符串的創建,這意味着只有須要的String對象才被創建。而若是你已經使用log4j,那麼你已經對於在if條件中使用debug語句這種變通方案十分熟悉了,但SLF4J的佔位符就比這個好用得多。 微信
這是你在Log4j中使用的方案,但確定這一點都不有趣而且下降了代碼可讀性由於增長了沒必要要的繁瑣重複代碼(boiler-plate code): 框架
1
2
3
|
if(logger.isDebugEnabled()) {
logger.debug("Processing trade with id: "+ id +" symbol: "+ symbol);
}
|
另外一方面,若是你使用SLF4J的話,你能夠獲得在極簡潔的格式的結果,就像如下展現的同樣: maven
1
|
logger.debug("Processing trade with id: {} and symbol : {} ",id, symbol);
|
在SLF4J,咱們不須要字符串鏈接並且不會致使暫時不須要的字符串消耗。取而代之的,咱們在一個以佔位符和以參數傳遞實際值的模板格式下寫日誌信息。你可能會在想萬一我有很個參數怎麼辦?嗯,那麼你能夠選擇使用變量參數版本的日誌方法或者用以Object數組傳遞。這是一個至關的方便和高效方法的打日誌方法。記住,在生產最終日誌信息的字符串以前,這個方法會檢查一個特定的日誌級別是否是打開了,這不只下降了內存消耗並且預先下降了CPU去處理字符串鏈接命令的時間。這裏是使用SLF4J日誌方法的代碼,來自於slf4j-log4j12-1.6.1.jar中的Log4j的適配器類Log4jLoggerAdapter。 性能
1
2
3
4
5
6
|
publicvoiddebug(String format, Object arg1, Object arg2) {
if(logger.isDebugEnabled()) {
FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
}
}
|
同時,咱們也很值得知道打日誌是對應用程序的性能有着很大影響的,在生產環節上只進行必要的日誌記錄是咱們所建議的。 學習
怎麼用SLF4J作Log4J的日誌記錄
除了以上好處,我想還有一個告誡,就是爲了使用SLF4J,你不只須要包含SLF4J的API jar包,例如 slf4j-api-1.6.1.jar,還須要相關Jar包,這取決於你在後臺使用的日誌類庫。若是你想要使用和Log4J 一塊兒使用SLF4J ,Simple Logging Facade for Java,,你須要包含如下的Jar包在你的classpath中,取決於哪一個SLF4J和你在使用的Log4J的版本。例如:
若是你在使用Maven去管理你的項目依賴,你只須要包含SLF4J JAR包,maven會包含它的依賴的相關包。爲了和SLF4J一塊兒中使用Log4J,你能夠包含如下的依賴在你項目中的pom.xml。
1
2
3
4
5
6
7
8
9
10
11
|
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
</dependency>
|
還有,若是你對於使用變量參數版本(variable argument version )的日誌方法感興趣的話,那麼就導入SLF4J 1.7的版本吧。
總結
總結此次說的,我建議使用SLF4J的而不是直接使用 Log4j, commons logging, logback 或者 java.util.logging 已經足夠充分了。
-- 掃描加關注,微信號: importnew --
原文連接: javarevisited 翻譯: ImportNew.com - Jaskey
譯文連接: http://www.importnew.com/7450.html