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

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

可是,大多數的應用開發(也包括我本身作過的應用),都沒有選擇commons-logging這個日誌框架,而是SLF4j 或者 Log4j 之類的。github

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

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

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

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

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

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

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

剛開始的時候,本身也不理解爲何添加這樣一個特殊的依賴且不用修改源碼就可讓Spring的日誌自動轉到 slf4j 上來呢?其實,不難理解,這真的是一個「接管」包,由於其內部的Log接口以及最經常使用的LogFactory類都與原來 commons-logging 中的同樣!因此,底層代碼就徹底不須要改變,同時,輸出日誌信息的方法調用就自動轉到了這個 jcl-over-slf4j 包的方法上。這樣就實現了「接管」。ui

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

經過這樣三步,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

相關文章
相關標籤/搜索