用好這幾個(gè)技巧状原,解決Maven Jar包沖突易如反掌

前言

大家在項(xiàng)目中肯定有碰到過(guò)Maven的Jar包沖突問(wèn)題挚赊,經(jīng)常出現(xiàn)的場(chǎng)景為:

本地運(yùn)行報(bào)NoSuchMethodError藻三,ClassNotFoundException洪橘。明明在依賴?yán)镉羞@個(gè)Jar包啊。怎么運(yùn)行不了?妹薄熄求?

項(xiàng)目中明明定義著某個(gè)jar包版本為2.0.2,怎么打包之后變成2.5.0了6焊拧弟晚?

A項(xiàng)目引xxx.jar包運(yùn)行好好的,B項(xiàng)目同樣引入xxx.jar后逾苫,運(yùn)行報(bào)錯(cuò)了卿城。。是B項(xiàng)目有問(wèn)題铅搓,還是xxx.jar包有問(wèn)題T逖?

本地環(huán)境和測(cè)試環(huán)境運(yùn)行的好好的狸吞,到了生產(chǎn)就報(bào)一堆NoSuchMethodError,是我人品有問(wèn)題還是生產(chǎn)環(huán)境有問(wèn)題V讣濉蹋偏?

這樣的問(wèn)題如果不熟悉maven依賴機(jī)制的同學(xué)排查起來(lái),估計(jì)挺頭痛的至壤。

而且maven依賴結(jié)構(gòu)不好的項(xiàng)目威始,在引入新的Jar包時(shí)的風(fēng)險(xiǎn)也是巨大的。小則影響性能像街,大則引起生產(chǎn)發(fā)布和運(yùn)行時(shí)異常黎棠。

其實(shí)以上問(wèn)題的根源都來(lái)自于Maven的Jar包沖突和使用不當(dāng)?shù)囊蕾噦鬟f晋渺。這篇文章我就好好分析下以下3個(gè)內(nèi)容:

  • 依賴傳遞的原則和產(chǎn)生Jar包沖突的原理分析
  • 定位沖突以及解決Jar包沖突的幾個(gè)簡(jiǎn)單技巧
  • 如何寫(xiě)一個(gè)干凈依賴關(guān)系的POM文件

依賴傳遞原則

幾乎所有的Jar包沖突都和依賴傳遞原則有關(guān),所以我們先說(shuō)Maven中的依賴傳遞原則:

最短路徑優(yōu)先原則

假如引入了2個(gè)Jar包A和B脓斩,都傳遞依賴了Z這個(gè)Jar包:

A -> X -> Y -> Z(2.5)

B -> X -> Z(2.0)

那其實(shí)最終生效的是Z(2.0)這個(gè)版本木西。因?yàn)樗穆窂礁佣獭H绻冶镜匾昧薢(3.0)的包随静,那生效的就是3.0的版本八千。一樣的道理。

最先聲明優(yōu)先原則

如果路徑長(zhǎng)短一樣燎猛,優(yōu)先選最先聲明的那個(gè)恋捆。

A -> Z(3.0)

B -> Z(2.5)

這里A最先聲明,所以傳遞過(guò)來(lái)的Z選擇用3.0版本的重绷。

Jar包沖突的原理

假設(shè)我們項(xiàng)目中依賴了A和B兩個(gè)Jar包沸停。而A和B各自又有以下傳遞依賴

A -> X -> Z(2.0)

B -> X -> Y -> Z(2.5)

那最終系統(tǒng)中Z包就產(chǎn)生了沖突,2.0和2.5兩個(gè)版本沖突昭卓。但是classpath中只會(huì)依賴一個(gè)版本的Z包愤钾。根據(jù)傳遞依賴的最短路徑優(yōu)先原則,最終依賴的應(yīng)該是2.0版本葬凳。

如果Y包中用了Z包2.5版本中新的method時(shí)候绰垂,當(dāng)運(yùn)行到這段邏輯的時(shí)候。就會(huì)報(bào)NoSuchMethodError了火焰。因?yàn)楸緛?lái)依賴的是2.5版本劲装,但是因?yàn)镴ar包沖突Maven選擇了2.0版本,2.0版本中又沒(méi)有這個(gè)新的method昌简,導(dǎo)致出錯(cuò)占业。

但要注意的是,不是所有沖突都會(huì)引起運(yùn)行異常纯赎。相反谦疾,大部分公司的項(xiàng)目都會(huì)有一些Jar包沖突,但其實(shí)沒(méi)有造成運(yùn)行時(shí)的問(wèn)題犬金。

這是因?yàn)楹芏鄠鬟f依賴的Jar包念恍,不管是2.0版本也好,2.5版本也好晚顷,都可以運(yùn)行峰伙。

只有高版本Jar包不向下兼容,或者新增了某些低版本沒(méi)有的API才有可能導(dǎo)致這樣的問(wèn)題

定位沖突

IDEA提供了一個(gè)maven依賴分析神器:Maven Helper

file

用這個(gè)插件能很好的顯示出項(xiàng)目中所有的依賴樹(shù)和沖突

file

這里面紅色高亮的部分该默,就表明這個(gè)Jar包有了沖突瞳氓。選中這個(gè)jar包,可以看到這2個(gè)版本的沖突的來(lái)源栓袖。

上圖的例子匣摘,表明cruator-client這個(gè)Jar包店诗,有2個(gè)傳遞依賴,分別為2.5.0版本和4.0.1版本音榜。沖突的描述為:

omitted for conflict with 2.5.0. 由于與2.5.0版本沖突而被省略

具體的層級(jí)在右邊也一目了然了庞瘸,所以maven最終根據(jù)最短路徑優(yōu)先原則選擇了2.5.0版本,4.0.1版本被忽略囊咏。

這時(shí)候有同學(xué)會(huì)問(wèn):本地環(huán)境我可以利用Maven Helper來(lái)定位恕洲,那么預(yù)生產(chǎn)或者生產(chǎn)環(huán)境呢。又沒(méi)有IDEA梅割,如何定位沖突的細(xì)節(jié)霜第?

可以利用mvn命令來(lái)解決:

mvn dependency:tree -Dverbose

此處一定不要省略-Dverbose參數(shù),要不然是不會(huì)顯示被忽略的包的

file

其實(shí)mvn命令行一樣好用户辞。非常清晰明確泌类。

解決Jar包沖突的幾個(gè)實(shí)用技巧

排除法

還是上面的那個(gè)例子,現(xiàn)在生效的是2.5.0底燎,如果想生效4.0.1刃榨。只需要在2.5.0上面點(diǎn)exclude就行了。

file

版本鎖定法

如果很多個(gè)依賴都傳遞了Jar包A双仍,涉及了很多個(gè)版本枢希,但是你只想指定一個(gè)版本。用排除法一個(gè)個(gè)去exclude太麻煩朱沃,而且exclude在pom文件中也會(huì)體現(xiàn)苞轿,太多的話,也影響代碼整潔和閱讀感受逗物。

這時(shí)候需要用到版本鎖定法

何謂版本鎖定法搬卒?公司的項(xiàng)目一般都會(huì)有父級(jí)pom,你想指定哪個(gè)版本只需要在你項(xiàng)目的父POM中(當(dāng)然在本工程內(nèi)也可以)定義如下:(還是舉上個(gè)例子翎卓,指定4.0.1版本)

<dependencyManagement>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-client</artifactId>
        <version>4.0.1</version>
    </dependency>
</dependencyManagement>

鎖定版本法可以打破2個(gè)依賴傳遞的原則契邀,優(yōu)先級(jí)為最高

鎖定版本后,依賴樹(shù)為:

file

都統(tǒng)一變成4.0.1失暴,鎖定版本有一個(gè)好處:版本鎖定并不排除Jar包坯门,而且顯示的把所有版本不一致的Jar包變成統(tǒng)一一個(gè)版本,這樣在閱讀代碼時(shí)比較友好逗扒。也不用忍受一大堆的exclude標(biāo)簽田盈。

如何寫(xiě)一個(gè)干凈依賴關(guān)系的POM文件

我本人是有些輕度代碼潔癖的人,所以即便是pom文件的依賴關(guān)系也想干凈而整潔缴阎。如何寫(xiě)好干凈的POM呢,作者認(rèn)為有幾點(diǎn)技巧要注意:

  • 盡量在父POM中定義<dependencyManagement>简软,來(lái)進(jìn)行本項(xiàng)目一些依賴版本的管理蛮拔,這樣可以從很大程度上解決一定的沖突
  • 如果是提供給別人依賴的Jar包述暂,盡可能不要傳遞依賴不必要的Jar包
  • 使用mvn dependency:analyze-only命令用于檢測(cè)那些聲明了但是沒(méi)被使用的依賴,如有有一些是你自己聲明的建炫,那盡量去掉
  • 使用mvn dependency:analyze-duplicate命令用來(lái)分析重復(fù)定義的依賴畦韭,清理那些重復(fù)定義的依賴

最后

其實(shí)龐大的項(xiàng)目依賴傳遞也一定多。但是不管多復(fù)雜的依賴關(guān)系肛跌,看到不要害怕艺配。就這么幾條原則,細(xì)心的去分析衍慎,所有的依賴都有跡可循转唉。

這些傳遞依賴如果管理的好,能讓你的維護(hù)成本大大降低稳捆。如果管不好赠法,這群野孩子每一個(gè)都可能是引發(fā)下一個(gè)NoSuchMethodError的導(dǎo)火索。

關(guān)注作者

如果你喜歡作者的文章乔夯,歡迎微信公眾號(hào)關(guān)注 「元人部落
一個(gè)只做原創(chuàng)的技術(shù)科技分享號(hào)

關(guān)注后回復(fù)“資料”獲取50G的技術(shù)資料

file
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末砖织,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子末荐,更是在濱河造成了極大的恐慌侧纯,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件甲脏,死亡現(xiàn)場(chǎng)離奇詭異眶熬,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)剃幌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)聋涨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人负乡,你說(shuō)我怎么就攤上這事牍白。” “怎么了抖棘?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵茂腥,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我切省,道長(zhǎng)最岗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任朝捆,我火速辦了婚禮般渡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己驯用,他們只是感情好脸秽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蝴乔,像睡著了一般记餐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上薇正,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天片酝,我揣著相機(jī)與錄音,去河邊找鬼挖腰。 笑死雕沿,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的曙聂。 我是一名探鬼主播晦炊,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼宁脊!你這毒婦竟也來(lái)了断国?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榆苞,失蹤者是張志新(化名)和其女友劉穎稳衬,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體坐漏,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡薄疚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了赊琳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片街夭。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖躏筏,靈堂內(nèi)的尸體忽然破棺而出板丽,到底是詐尸還是另有隱情,我是刑警寧澤趁尼,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布埃碱,位于F島的核電站,受9級(jí)特大地震影響酥泞,放射性物質(zhì)發(fā)生泄漏砚殿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一芝囤、第九天 我趴在偏房一處隱蔽的房頂上張望似炎。 院中可真熱鬧辛萍,春花似錦、人聲如沸羡藐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)传睹。三九已至,卻和暖如春岸晦,著一層夾襖步出監(jiān)牢的瞬間欧啤,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工启上, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留邢隧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓冈在,卻偏偏與公主長(zhǎng)得像倒慧,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子包券,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355