日志SLF4J解惑

0x00 前言

作為后端開發(fā)修肠,日志可能是我們最常用的功能之一了。平時大家也可能經(jīng)常遇見日志沖突煎殷,常見的overflow報錯,今天為大家詳解一下腿箩,這其中的原理以及問題所在豪直。本文涉及 jar 包有:log4j,log4j-over-slf4j,slf4j-api,slf4j-log4j12 等等。

0x01 背景

不知道大家在平時開發(fā)中珠移,是否經(jīng)常遇見以下幾個問題:

  • log4j,logback等等日志包沖突弓乙,然后再慢慢排除,不勝其煩钧惧。
  • 使用了 slf4j 暇韧,但是又遇到 StackOverflwError 錯誤。
    image
  • 好不容易解決了StackOverflwError浓瞪,可能又遇到了類似如圖所示的錯誤:
    image
  • ......

0x02 概述

什么是 SLF4J 呢懈玻?簡而言之,他就是一個日志的門面乾颁,市場上的日志系統(tǒng)非常多涂乌, SLF4J 想做的一件事情,就是將這多種的日志系統(tǒng)包裝起來英岭,提供統(tǒng)一的 API 供調用湾盒,從而解決日志的列國爭霸的情況。

0x03 SLF4J 調用流程

在解決以上問題之前诅妹,讓我們先對日志系統(tǒng)做一個大概的理解罚勾。到底什么是 log4j,什么是 slf4j-api,為什么有一個 slf4j-log4j12,又怎么有個log4j-over-slf4j,看上去頭暈眼花吭狡,繞來繞去荧库。先祭上一張官網(wǎng)圖:
image

相信大家都見過這張圖,但是未必全都理解圖上說的是什么意思赵刑。所以呢分衫,我們先不講圖,先看看最上面的一排文字般此,SLF4J bound to xxxx,xxxx總共涉及:

  1. null
  2. logback-classic
  3. log4j
  4. java.util.logging
  5. simple
  6. no-operation

第1個顧名思義蚪战,不綁定,就是沒有日志實現(xiàn)铐懊。第5邀桑,6可以看出來,是 SLF4J 自己的實現(xiàn)科乎,這里就忽略不講壁畸。所以著重講一下2、3、4捏萍。他們有個共同的特點太抓,就是他們都是日志的真正實現(xiàn)庫,他們和SLF4J沒有關系令杈,你可以使用 logback 打印日志走敌,也可以使用 log4j 打日志。

第一層逗噩, application 就是應用層掉丽。

看看圖中第二層,統(tǒng)統(tǒng)都是 SLF4J API异雁。那么這一層是干什么用的呢捶障?這一層就是一個門面層,而和門面層息息相關的 jar 包是什么呢纲刀?對残邀,就是圖中的 slf4j-api.jar 。這個jar包中柑蛇,提供了日志調用的所有接口,應用都是直接調用這個 jar 包中的接口進行日志調用驱闷。

第三層有點不同耻台。第一列,無實現(xiàn)空另,第2盆耽,5,6都是原生的一個實現(xiàn)扼菠,而3摄杂,4都有一個適配層。這里說說 logback循榆。logback 他為什么不需要適配層呢析恢,因為他就是按照了 SLF4J 接口去實現(xiàn)的一個日志庫,相當于親兒子秧饮,自然不需要適配層映挂。所以,logback-classic.jar 和 logback-core.jar 就是 logback 的底層實現(xiàn)盗尸。而3柑船,4就不同了,他們的接口或多或少會有差異泼各,調用方式也各不相同鞍时,所以,需要一個適配層。所以 slf4j-log412.jar 和 slf4j-jdk14.jar 包的作用就是一個適配逆巍,這里是一個橋接及塘,應用通過 slf4j-api 的接口調用過來時,橋接類實際會調用其底層的實現(xiàn)蒸苇,達到一個橋接的過程磷蛹。所以,slf4j-log412.jar,slf4j-jdk14.jar,slf4j-simple.jar,slf4j-nop.jar 是同一類溪烤,就是把-右邊的實現(xiàn)進行一個橋接味咳。

第四層,可以看到第2檬嘀,3對應的實現(xiàn)槽驶,log4j.jar 和 jvm 就是最后的實現(xiàn)。

至此鸳兽,做一個小總結:

  1. slf4j-api.jar 是上層的門面掂铐,里面提供接口供調用。
  2. logback-classic.jar, logback-core.jar, log4j.jar, 是同一類別揍异,屬于底層實現(xiàn)庫全陨。
  3. slf4j-log412.jar,slf4j-jdk14.jar,slf4j-simple.jar,slf4j-nop.jar,可以看成 slf4j-xxxx.jar,屬于同一個類別衷掷,就是對 - 后面的庫做一個橋接辱姨,更簡單的理解,從左到右讀:把 - 左邊的調用用右邊的庫實現(xiàn)戚嗅。

此時再看看上面那張圖雨涛,是否已經(jīng)全部理解了呢?

0x04 SLF4J 轉換流程

如果看完上面懦胞,不覺得 SLF4J 有什么好處替久,就來看看下面這張圖:
image

那這張圖又是什么意思呢?這就要說到 SLF4J 的一個強大之處了躏尉。設想一下以下一種情況:新建了一個工程蚯根,引入的第一個庫使用的是 java.util.logging 日志庫,引入的第二個庫使用的是 log4j 日志庫胀糜,而你自己的工程稼锅,老板規(guī)定,必須要用 logback 僚纷。你怎么辦呢矩距?這個時候, SLF4J 就出場了怖竭。他能幫你把所有日志歸攏到你所指定的一種日志實現(xiàn)锥债。就是說,他可以把 jul 日志實現(xiàn)轉成 logback,還能把 log4j 實現(xiàn)轉成 logback哮肚。那他是怎么做的呢登夫?回過頭來看圖吧。

著重講解左上角這一部分允趟,其他的類似恼策。

先看 application,這個是應用潮剪,可以看到涣楷,他也遇到了我說到的問題。他的依賴里面有使用 log4j 的抗碰,有用 commons logging 的狮斗,有用 java.util.logging 的。所以此時需要做一個替換弧蝇,分別是通過 jcl-over-slf4j.jar 替換掉 commons-logging.jar,log4j-over-slf4j.jar 替換掉 log4j.jar, jul-to-slf4j.jar 包中安裝 SLF4JBrindgeHandler 解決碳褒。替換掉之后,就把所有日志調用轉接到 slf4j-api 上了看疗,然后 api 接口再調用底層實現(xiàn)沙峻,圖上是 logback。文中說的替換是什么意思呢两芳?就是把原日志實現(xiàn)庫排除掉摔寨,引入 xxx-over-slf4j.jar 。

那么盗扇,xxx-over-slf4j.jar 是什么原理呢?先給大家看這張圖:


image

左邊是 log4j.jar 的包結構沉填,右邊是 log4j-over-slf4j.jar 的包結構疗隶。發(fā)現(xiàn)貓膩了嗎?他們的目錄結構一模一樣翼闹!所以用 log4j-over-slf4j 可以替換掉 log4j斑鼻!且編譯不會出錯。log4j-over-slf4j.jar 實現(xiàn)了基本上所有 log4j 會被調用的 api 接口猎荠。所以替換之后坚弱,不會報錯,編譯也能通過关摇,而底層實現(xiàn)卻全轉到 slf4j 這里去了荒叶。這里就是一個貍貓換太子的把戲。

再看其他兩個圖输虱,底層分別是 log4j, jvm 實現(xiàn)些楣。都是講其他庫 over 一下到 slf4j 。

特別注意一下, logback 不需要轉愁茁,為什么蚕钦?因為他是親兒子。天生就帶這些鹅很。

所以再小總結一下:

  • jcl-over-slf4j.jar, log4j-over-slf4j.jar, jul-to-slf4j.jar嘶居,這種形式類似 xxx-over-slf4j.jar 的,就是將 - 前的太子用 slf4j 的貍貓代替促煮。而 xxx-to-slf4j.jar 比較特殊邮屁,這是因為 xxx 這個包無法被替換掉,比如 java.util.logging,系統(tǒng)的庫污茵,無法替換樱报,所以只能采用別的手段。此類別的實現(xiàn)讀者有興趣可以去看看泞当,本文不再分析迹蛤。

0x05 常見問題解決

StackOverflow 錯誤

為什么會出現(xiàn)這個問題呢?控制臺輸出上一般會比較清楚襟士,就是你既使用了橋接庫盗飒,又使用了over庫(貍貓)。比如:
image

試想一下:你先用 over 庫把 log4j 轉成了 slfj4 調用陋桂。緊接著逆趣,你又把 slf4j 適配到 log4j 上。這就構成了一個死循環(huán)嗜历,肯定是會出現(xiàn)堆棧溢出的問題宣渗。所以,一個工程里面梨州,只能保留一個日志實現(xiàn)庫痕囱,還有配套的橋接庫,加上其他日志的 over 庫暴匠,才是正確之道鞍恢。

異常參數(shù)錯誤

上面提到的這個錯誤:


image

大致可以看出來吧,他缺少一個真正的實現(xiàn)每窖“锏簦看你選擇使用什么,就把什么庫補充上去窒典。加上 logback蟆炊,去掉 slf4j-log4j 或者加上 log4j 都可以解決這個問題。

其他問題都比較類似瀑志,如果看懂了上文的介紹盅称,應該可以著手解決此類問題了肩祥。

0x06 不算總結的總結

了解了日志的原理,以后媽媽再也不擔心日志沖突了缩膝!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末混狠,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疾层,更是在濱河造成了極大的恐慌将饺,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痛黎,死亡現(xiàn)場離奇詭異予弧,居然都是意外死亡,警方通過查閱死者的電腦和手機湖饱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門掖蛤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人井厌,你說我怎么就攤上這事蚓庭。” “怎么了仅仆?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵器赞,是天一觀的道長。 經(jīng)常有香客問我墓拜,道長港柜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任咳榜,我火速辦了婚禮夏醉,結果婚禮上,老公的妹妹穿的比我還像新娘涌韩。我一直安慰自己畔柔,他們只是感情好,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布贸辈。 她就那樣靜靜地躺著释树,像睡著了一般肠槽。 火紅的嫁衣襯著肌膚如雪擎淤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天秸仙,我揣著相機與錄音嘴拢,去河邊找鬼。 笑死寂纪,一個胖子當著我的面吹牛席吴,可吹牛的內容都是我干的赌结。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼孝冒,長吁一口氣:“原來是場噩夢啊……” “哼柬姚!你這毒婦竟也來了?” 一聲冷哼從身側響起庄涡,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤量承,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后穴店,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體撕捍,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年泣洞,在試婚紗的時候發(fā)現(xiàn)自己被綠了忧风。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡球凰,死狀恐怖狮腿,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情弟蚀,我是刑警寧澤蚤霞,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站义钉,受9級特大地震影響昧绣,放射性物質發(fā)生泄漏。R本人自食惡果不足惜捶闸,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一夜畴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧删壮,春花似錦贪绘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亿虽,卻和暖如春菱涤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背洛勉。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工粘秆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人收毫。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓攻走,卻偏偏與公主長得像殷勘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子昔搂,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容