Spring源碼學習:第2步--使用SLF4j+Log4j日志框架替換掉其自身的commons-logging日志框架


正如Spring官方文檔所述,其底層的實現選擇了commons-logging作為日志框架。這一“失足”性的選擇,竟連Spring自身都抱怨。但是,誰叫Spring如此優秀呢,即使有一點小瑕疵,人家也得完美的兼容下去。所以,直到目前的版本,commons-logging仍然是默認的日志框架。

但是,大多數的應用開發(也包括我自己做過的應用),都沒有選擇commons-logging這個日志框架,而是SLF4j 或者 Log4j 之類的。

那有沒有辦法,像其它很多開源框架一樣,替換掉其默認的commons-logging呢?顯然,是有的!

從Spring官方文檔中可以看出,它其實也只有 spring-core 這個模塊依賴了commons-logging,所以,替換掉它就可以了。

以使用SLF4j框架來替換為例,具體的替換步驟如下(參照官網):

  1. 從 spring-core 的依賴中排除掉 commons-logging 依賴。
  2. 添加 jcl-over-slf4j 依賴。
  3. 添加 slf4j 以及 log4j 依賴。

詳細說明如以下截圖所示:

第一步:排除對 commons-logging 的依賴。

第二步:添加接管 commons-logging 的依賴。

剛開始的時候,自己也不理解為什么添加這樣一個特殊的依賴且不用修改源碼就可以讓Spring的日志自動轉到 slf4j 上來呢?其實,不難理解,這真的是一個“接管”包,因為其內部的Log接口以及最常用的LogFactory類都與原來 commons-logging 中的一樣!所以,底層代碼就完全不需要改變,同時,輸出日志信息的方法調用就自動轉到了這個 jcl-over-slf4j 包的方法上。這樣就實現了“接管”。

第三步:添加 slf4j 及 log4j 依賴。

通過這樣三步,commons-logging 的日志方法調用就全部轉嫁到 jcl-over-slf4j,再到 slf4j 最后到 log4j 上面了。

我沒有直接使用 Log4J 來接管,因為 slf4j 比 log4j 更好一些(主要體現在占位符以及Debug和Trace日志不用全部拼接字符串的邏輯上)。

現在Spring官方文檔的格式好像改版了,沒有以前那樣可以直接在一個Html頁面中顯示出來(進而可以保存為PDF並打印)。所以,在此貢獻一個我當年從單個Html頁面中保存下來的PDF文檔吧。同時,上述接管 commons-logging 的原文也可以在第2章中找到。

本PDF是Spring的 4.3.5.RELEASE 版本。

鏈接地址:https://github.com/cyhbyw/spring-framework/blob/Branch_v4.2.5.RELEASE/Spring%20Framework%20Reference%20Documentation.pdf

============================================================================================================================

上面的接管其實還比較簡單,而且也能看到,這是在Spring源碼之外且基於Maven來管理的。問題是:如何在Spring源碼中替換呢?

Spring源碼使用了Gradle來管理,所以,應該能夠想到,是通過直接修改 build.gradle 文件來完成的。

我自己在GitHub上Checkout出來后使用的是 4.2.5.RELEASE 版本,可以看到,這個版本的 build.gradle 文件有1400+行。自己沒有系統學習和使用過Gradle,於是,依照着對maven的理解,開始改吧。

依舊可以清晰地看到,Spring下的十幾個模塊在 build.gradle 文件中都有類似於 project("spring-core") 這樣的關鍵字。在這其中還可以看到 dependencies 關鍵字,不用想,這和Maven中的 dependencies 一樣,就是依賴了。

明顯,commons-logging 的依賴位列其中。所以,想辦法將它替換成 slf4j 應該就可以了。

可是,咋個改呢??

開始的嘗試(第一次)是:

  1. 刪除 commons-logging 這一行的依賴
  2. 添加 jcl-over-slf4j 依賴、slf4j-api 依賴以及 slf4j-log4j12 依賴(都是 compile 范圍)
  3. 將 optional 的 log4j 依賴改為 compile

為什么要這樣做呢?很簡單,完全是從上面的Maven中照搬過來的!然而,悲劇發生了,改了后它就是不正常。更奇怪的是,它會報 spring-context 對 spring-beans-groovy 的依賴找不到!

完全無解,憋了好久也沒想出個辦法。。。

完全無解,憋了好久也沒想出個辦法。。。

完全無解,憋了好久也沒想出個辦法。。。

沒辦法,只有嘗試了。整個操作的現象就是,添加了上述依賴后,它就報 spring-context 對 spring-beans-groovy 的依賴找不到!於是,我少少地添加唄,再不濟,一個一個地添加唄。

現在的嘗試(第N次)是:

  1. 刪除 commons-logging 這一行的依賴——因為要排除掉 commons-logging 的依賴,所以這一步是必須的!
  2. 添加 jcl-over-slf4j 依賴、slf4j-api 依賴以及 slf4j-log4j12 依賴(都是 compile 范圍)——因為排除 commons-logging 后,源碼中直接報錯,沒有需要的類,所以,這些依賴必須加進來。

只操作了上述兩步,再一試,還是報錯,但錯誤不一樣了,而且一看就懂,大概就是說找不到類,而且是 log4j 中的 Log 類(其實是接口),而且錯誤是在 spring-context 是報出來的,於是,嘗試再在 spring-context 的依賴中添加 log4j 的依賴。結果,成了!

 

 對Gradle不熟悉,所以,雖然問題是解決了也可以正常運行了,但是,RootCause還是不清楚。而且從上述截圖中也可以看到 spring-core 的依賴中已經有 optional 的 log4j 依賴了,而我之前是直接把這個 optional 改成 compile 了,會不會有影響?而最后能正常運行的時候,這個 optional 的 log4j 仍然是存在的,只是在 spring-context 中添加了 compile 的 log4j。

 

獻上自己從GitHub Fork並“踐踏”過的Spring源碼地址:https://github.com/cyhbyw/spring-framework/tree/Branch_v4.2.5.RELEASE


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM