閱讀991 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《SLF4J官方文檔》SLF4J-FAQ 常見問題解答(一)

一般性問題

  1. 什麼是SLF4J?
  2. 什麼時候應該使用SLF4J?
  3. SLF4J仍是另一個日誌外觀嗎?
  4. 如果SLF4J可修複JCL,那為什麼不在JCL裏加入修複而是創建一個新項目?
  5. 使用SLF4J時,我必須重新編譯我的應用以轉換到一個不同的日誌係統嗎?
  6. SLF4J的要求是什麼?
  7. SLF4J向後兼容版本嗎?
  8. 使用SLF4J時遇到訪問權限錯誤,原因是什麼?
  9. 為什麼SLF4J是在X11類型許可證下許可而不是Apache軟件許可?

10.在哪裏能獲得特定的SLF4J綁定?

11.我的庫應該嚐試配置logging嗎?

12.為了減小我們軟件的依賴庫數量,我們想讓SLF4J成為一個可選擇的依賴包。這個是好主意嗎?

13.Maven傳遞依賴怎麼樣?

14.如何排除依賴Maven的commons-logging?

 

關於SLF4J API

  1. 為什麼日誌器接口的打印方法不接收對象類型的消息,但隻收String類型消息?
  2. 我可以輸出一個沒有消息的異常日誌嗎?
  3. 輸出日誌(關閉日誌)的最快方法是什麼?
  4. 如何打印單獨(可能是複雜的)對象的字符串內容日誌?
  5. 為什麼slf4j.Logger接口沒有FATAL級別的方法?
  6. 為什麼TRACED級別的日誌隻在SLF4J 1.4.0版本介紹?
  7. SLF4J日誌API支持I18N(國際化)嗎?
  8. 不通過LoggerFactory裏的靜態方法,可以重新獲取日誌器嗎?
  9. 存在錯誤/拋出異常時,可以參數化日誌聲明嗎?

實現SLF4J API

  1. 如何使我的日誌底層SLF4J可兼容?
  2. 如何使我的日誌係統添加支持Marker接口?
  3. SLF4J的版本檢查機製如何工作?

關於日誌的一般性問題

1.類的日誌器成員變量應該聲明為靜態變量嗎?

2.類裏的聲明日誌器有推薦的習語嗎?

一般性問題

1.什麼是SLF4J?

SLF4J是一個簡單的日誌係統外觀,它允許終端用戶在部署時植入所需日誌係統。

2.什麼時候應該使用SLF4J?

簡單而言,為庫和其他嵌入組件的日誌需求,它們應該考慮下SLF4J,因為庫不能強加終端用戶日誌框架的選擇。另外,獨立應用使用SLF4J不一定有意義。獨立應用可以直接援引他們選擇的日誌框架。對於logback,問題是沒有實際意義的,因為logback通過SLF4J暴露它的logger API。

SLF4J隻是個外觀,意味著它不提供一個完整的日誌方案。例如配置輸出源或者設置日誌級別的操作不能和SLF4J執行。因此,在某個時間點上,任何微不足道的應用將需要直接援引底層日誌係統。換句話說,完全對立的API底層日誌係統是不可能給獨立應用程序使用的。然而,SLF4J減少這種依賴的影響到無痛苦級別。

假設你的CRM應用用log4j來記錄日誌。然後,你的一個重要客戶端請求日誌要通過JDK1.4執行日誌記錄。如果你的應用充斥著數以千計的直接log4j調用,轉移到JDK1.4的調用將相對是一個冗長和容易出錯的過程。更糟的是,你可能需要維護兩個版本的CRM軟件。你已經引用SLF4J API而不失log4J,通過替換二者的jar文件,遷移可在幾分鍾內完成。

SLF4J允許組件開發人員推遲終端用戶的日誌係統的選擇,但最終仍需要做出一個選擇。

3.SLF4J仍是另一個日誌外觀嗎?

SLF4J在概念上和JCL非常相似。因此它可以被認為是另一個日誌外觀。但是,SLF4J在設計上更簡單和更健壯。簡而言之,SLF4J避免了植入JCL的類加載問題。

4.如果SLF4J可修複JCL,那為什麼不在JCL裏加入修複而是創建一個新項目?

這是非常好的問題。首先,SLF4J靜態綁定方法非常簡單,甚至很可笑。很難說服開發者這個方法的有效性。僅僅在SLF4J發布後和開始變得被接收後,它才在相關社區裏獲得尊重。

其次,SLF4J提出2個改進手段,這都趨向被低估了。用務實的方法,參數化日誌消息解決了一個跟日誌性能聯係的重要問題。標記對象,由org.slf4j.Logger接口支持,為高級日誌係統的采用鋪路,如果必要的話,同時讓放開轉回更多傳統日誌係統的大門。

5.使用SLF4J時,我必須重新編譯我的應用以轉換到一個不同的日誌係統嗎?

不,你不需要重新編譯你的應用。你可以通過移除之前的SLF4J綁定,然後將它替換為你選擇的綁定,就能轉換到不同的日誌係統了。

例如,如果你在使用NOP實現,希望轉換到log4j 1.2版本,在你的類目錄下用 slf4j-log4j12.jar 替換slf4j-nop.jar,但也別忘了添加log4j-1.2.x.jar 。像轉換到JDK 1.4 logging?隻需用slf4j-jdk14.jar替換slf4j-log4j12.jar

6.SLF4J的要求是什麼?

1.7.0版本SLF4J需要JDK1.5以上。早期的SLF4J版本,像SLF4J 1.4,1.5和1.6,要求JDK1.4。

 

Binding Requirements
slf4j-nop JDK 1.5
slf4j-simple JDK 1.5
slf4j-log4j12 JDK 1.5, plus any other library dependencies required by the log4j appenders in use加入任何其他所需的依賴包取決於使用的log4j輸出源
slf4j-jdk14 JDK 1.5 or later
logback-classic JDK 1.5 or later, plus any other library dependencies required by the logbackappenders in use加入任何其他所需的依賴包取決於使用的log4j輸出源

7.SLF4J向後兼容版本嗎?

從客戶端角度,SLF4J API對所有版本都向後兼容。這意味著你能從SLF4J版本1.0升級到任何以後的版本,沒有任何問題。對於slf4j-api版本N和slf4j-api

版本M, 版本N編譯的代碼將和版本M編譯的代碼一起正常運作。迄今為止, slf4j-api裏的二進製兼容性從來沒有被打破。

然而,從客戶端角度,SLF4J API非常穩定時,SLF4J綁定,比如slf4j-simple.jar

或slf4j-log4j12.jar,需要一個特定版本的SLF4J-API。混合不同版本的slf4j可能會出現問題和強烈不提倡的。例如,如果你正在使用slf4j-api-1.5.6.jar,然後你也應該使用slf4j-simple-1.5.6.jar,使用slf4j-simple-1.4.2.jar將不會工作。

在初始化時時,如果SLF4J推測可能有版本不匹配問題,它將發出一個關於不匹配的警告。

8.使用SLF4J時遇到訪問權限錯誤,原因是什麼?

如下是錯誤詳情:

1 Exception in thread "main" java.lang.IllegalAccessError: tried to access field
2 org.slf4j.impl.StaticLoggerBinder.SINGLETON from class
3 org.slf4j.LoggerFactory    at
4 org.slf4j.LoggerFactory.<clinit>(LoggerFactory.java:60)

這個問題是由LoggerFactory類的靜態初始化嚐試直接訪問org.slf4j.impl.StaticLoggerBinder的單例變量造成的。這在SLF4J 1.5.5和之前的版本允許,在1.5.6及以後的版本,單例變量已經被標記為私有訪問權限了。

如果你遇到了上述的錯誤,你可以用老版本的slf4j-api,比如1.4.3,同時使用一個新版本的slf4j綁定,比如1.5.6。通常,當你的Maven pom.xml文件使用hibernate 3.3.0,在slf4j-api 1.4.2版本上聲明一個依賴時,將發生上述異常。如果你的pom.xml在slf4j綁定上聲明依賴,比方說slf4j-log4j12 版本1.5.6,你會觸發非法訪問錯誤。

查看Maven裏那個slf4j-api版本被拉入,用下述maven依賴植入。

1 mvndependency:tree

如果你使用Eclipse,請不要依靠m2eclipse顯示的關係樹。
如果你的pom.xml明確在slf4j-api上聲明了依賴,這個版本的api匹配已聲明的綁定,將使這個問題消失。
也請讀向後兼容性的FAQ,以獲得更多普遍性解釋。
9.為什麼SLF4J是在X11類型許可證下許可而不是Apache軟件許可?
SLF4J是在X11類型許可證下許可而不是Apache軟件許可,這是因為X11許可是被Apache軟件基金會以及自由軟件基金會的各自許可認為是科兼容的。
10.在哪裏能獲得特定的SLF4J綁定?

SimpleLoggerNOPLoggerog4jLoggerAdapterJDK14LoggerAdapter 的SLF4J綁定包含在slf4j-nop.jarslf4j-simple.jar,slf4j-log4j12.jar, and slf4j-jdk14.jar文件裏。

給logback-classic的綁定附帶在logback distribution(https://logback.qos.ch/download.html)上。對於其他所有的綁定,logback-classice綁定需要slf4j-api.jar。

11.我的庫應該嚐試配置logging嗎?

嵌入的組件,比如庫,不進不需要配置底層日誌框架,它們也不應該做這些。它們應該引入SLF4j來記錄日誌,但也應該讓終端用戶配置日誌環境。當嵌入的組件嚐試在自己配置日誌時,它們常常會覆蓋終端用戶的意願。在一天的結束時,終端用戶不得不讀日誌,處理日誌。她應該是決定自己想要的日誌配置的人。

12.為了減小我們軟件的依賴庫數量,我們想讓SLF4J成為一個可選擇的依賴包。這個是好主意嗎?

當一個軟件工程到達它需要設計日誌策略的點時,這個問題會提起 。

讓Wombat成為一個具有極少依賴的軟件庫。如果SLF4J被選作為Wombat的日誌API,那麼一個新的slf4j-api.jar依賴庫將被加入帶Wombat的依賴包列表中。由於寫日誌的包裝並不難,一些開發者冒險包裝SLF4J,隻有當它已經出現在類路徑中時鏈接它,使得SLF4J成為Wombat的一個可選擇的依賴庫。為了解決這個依賴問題,包裝將被從SLF4J的API中隔離Wombat,以確保Wombat中的日誌不會過時的。

另外,任何SLF4J-包裝都取決於SLF4J得定義。它們一定有相同的通用api。在將來,如果出現一個新的、明顯不同的日誌API,和直接使用SLF4J的代碼一樣,使用包裝器的代碼也將同樣很難移植到新的API.因此,包裝器不可能是麵向未來的代碼,但在SLF4J上增加了一個額外的間接連接,使得這更複雜,這本身就是一中間接連接。

脆弱性增加實際上比這個還遭。包裝器需要依賴隨時變化的一些內部SLF4J接口,這違背了麵向客戶端API永不改變的原則。因此,包裝器通常依賴一些同他們一起編譯的主要版本。針對SLF4J 1.5.x版本編譯的包裝器將不會同SLF4J 版本1.6工作,但是使用org.slf4j.Logger, LoggerFactory, MarkerFactory, org.slf4j.Marker和MDC的客戶端代碼將和任何版本SLF4J 1.0及以後的版本正常工作。合理地假設在大部分工程中,Wombat將是許多依賴庫中的一個。如果每個依賴庫有自己日誌包裝器,那麼大概每個包裝器需要獨立配置。因此,不隻是處理SLF4J的日誌框架,Wombat的用戶也必須處理Wombat的日誌包裝器。

為了使SLF4J可選擇,每個框架提出的自己的包裝器將加劇這個問題。(配置或處理5個不同的日誌包裝器將很不愉快,也不招人喜歡)

Velocity項目采納的日誌策略 是一個“自定義日誌抽象”反模式的好例子。通過采用一個獨立的日誌抽象的策略,Velocity開發者已經使自己的開發更複雜,但更重要的是,他們讓開發對他們的用戶更難。

一些項目試著在類路勁上檢測SLF4J的存在性,如果存在的話就轉換到SLF4J.雖然這個方法看上去足夠的透明,但是它將導致錯誤的位置信息。底層日誌框架將打印包裝器的位置(類名和行數)而不是打印真正調用者的位置。還有就是除了參數化日誌、像SLF4J支持MDC和標記的API覆蓋問題。盡管有人可以在數小時內提出一個似乎可運行的SLF4J包裝器,隨著時間的推移,許多技術問題將出現,這是Wombat開發者不得不處理的問題。注意SLF4J已經發展了好幾年了,有260個bug報告提起它。

基於以上原因,框架的開發者應該抵製自己寫的日誌包裝的誘惑。 它不僅是浪費開發者時間,對上述日誌的用戶,這實際上讓開發更困難,使日誌代碼自相矛盾地更容易改變。

13.Maven傳遞依賴怎麼樣?

作為使用Maven構建庫作者,你可能想使用綁定來測試你的應用程序,比如SLF4J-log4j12或的logback經典,對用戶不強製log4j或logback-classic作為依賴。 這是比較容易做到的。

基於你的庫的代碼依賴於SLF4J API,你需要聲明SLF4J的API作為一個編譯時(默認範圍)的依賴。

1 <dependency>
2   <groupId>org.slf4j</groupId>
3   <artifactId>slf4j-api</artifactId>
4   <version>1.7.21</version>
5 </dependency>

通過聲明SLF4J綁定依賴為“測試”的範圍,可以實現限製在測試綁定使用的SLF4J的傳遞。例如:

1 <dependency>
2   <groupId>org.slf4j</groupId>
3   <artifactId>slf4j-log4j12</artifactId>
4   <version>1.7.21</version>
5   <scope>test</scope>
6 </dependency>

 

因此,至於你的用戶要導出SLF4J的API作為庫的傳遞依賴,但不是任何SLF4J綁定或任何底層日誌係統。

需要注意的是由於SLF4J 1.6版,在沒有SLF4J綁定,SLF4J的API將默認為無無操作實現。

14.如何排除依賴Maven的commons-logging?

替代1明確排除

很多使用Maven的軟件項目聲明commons-logging作為一個依賴。因此,如果你希望遷移到SLF4J或使用jcl-over-slf4j,你需要排除項目中所有依賴裏的comms-logging,這些依賴庫傳遞依賴common-logging。依賴排除 在Maven文件裏已有描述。為分布在幾個pom.xml裏的多個依賴明確地排除common-logging,可能是一個笨重的和相對容易出錯的過程。

替代2規定的範圍

在項目的pom.xml文件中所提供的範圍內,通過聲明Commons-logging,它可以像依賴一樣簡單、方便地排除。實際的commons-logging類將由jcl-over-slf4j提供。 這轉化為以下POM文件片段:

01 <dependency>
02   <groupId>commons-logging</groupId>
03   <artifactId>commons-logging</artifactId>
04   <version>1.1.1</version>
05   <scope>provided</scope>
06 </dependency>
07  
08 <dependency>
09   <groupId>org.slf4j</groupId>
10   <artifactId>jcl-over-slf4j</artifactId>
11   <version>1.7.21</version>
12   </dependency>

 

第一依賴性聲明本質規定commons-logging會通過你的環境“以某種方式”提供。第二個聲明引入jcl-over-slf4j到你的項目中。 作為jcl-over-slf4j是commons-logging完美的二進製兼容更換,第一個斷言為真。

不幸的是,雖然在規定範圍內聲明的commons-logging能夠完成任務,你的IDE,比如Eclipse中,仍將在項目的類路徑上放置commons-logging.jar,通過你的IDE可以看到。 您將需要確保jcl-over-slf4j前,您的IDE 的commons-logging.jar的是可見的。

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-19 16:01:58

  上一篇:go  《SLF4J官方文檔》SLF4J-FAQ 常見問題解答(二)
  下一篇:go  《經驗之談》想要做好SEO推廣必知要事,峰任策劃告訴您。