2021-07 Maven的依賴管理

Maven的依賴管理

Maven中的依賴scope

scope定義了依賴的項目在編譯椎组、測試、打包三個不同階段是否生效,下面列舉了三個階段中依賴是否生效的具體表現(xiàn)店枣,以加深理解:

首先是編譯階段,這個階段將用戶的java文件編譯成class文件灌闺,如果依賴在這個階段不生效艰争,那么當用戶的主代碼中使用了該依賴中的類時,會造成編譯失敗桂对。具體現(xiàn)象是mvn compile失敗甩卓,或者更直觀的,在ide中提示找不到類蕉斜,編譯錯誤逾柿。

然后是測試階段,如果依賴在測試階段不生效宅此,那么如果用戶在測試代碼中使用了該依賴中的類机错,會引起測試代碼編譯失敗。

最后是打包階段父腕,如果依賴在打包階段不生效弱匪,簡單來說,打包后的文件中不會存在該依賴的jar包璧亮。這樣打包后的文件萧诫,在后續(xù)運行階段需要另外提供該依賴的jar包斥难,否則當jvm嘗試將該依賴中的class文件加載到內(nèi)存中時,會報錯找不到類帘饶。在不同的打包場景下哑诊,依賴是否生效的具體表現(xiàn)也是不同的,需要具體場景具體分析:

  • 打war包:依賴是否生效意味著及刻,該依賴的jar包是否出現(xiàn)在WEB-INF/lib目錄中
  • maven-assembly-plugin打jar包(包含依賴的包):依賴是否生效意味著镀裤,是否將該依賴的jar包打進去(默認配置下的表現(xiàn),實際上assembly-plugin配置自由度很高)
  • maven-jar-plugin打普通的jar包(只包含主代碼):依賴是否生效意味著缴饭,如果指定了addClasspath暑劝,那么MANIFEST.MF中是否包含該jar包的路徑

依賴在上述三個階段是否生效有多種排列組合,maven定義了多個scope來描述這些場景茴扁,官方文檔說明中共有6種scope:compile provided runtime test system import铃岔,常用和需要關注的有5種 compile provided system runtime test,而import比較特殊峭火,使用的場景和其他幾種完全不同毁习,這里暫時不討論。

這些scope和依賴在三個階段是否生效的關系如下:

編譯 測試 打包
compile
runtime
provided/system
test

可以看到卖丸,依賴配置任何scope對于測試階段都是生效的纺且,相當于scope對測試其實是透明的,只要聲明了依賴稍浆,對測試來說就是生效的载碌。

那么這幾種scope一般用在什么場景下呢?

compile是默認的配置衅枫,適用的場景是:如果依賴在編譯階段需要引入(用戶寫的主代碼引用了依賴中的類)嫁艇,而且期望打包到lib中,那么就要聲明為compile弦撩。

runtime適用的場景:編譯階段不需要步咪,比如對于jdbc的具體實現(xiàn)mysql-jdbc,由于代碼中直接使用的是jdbc的接口益楼,所以編譯階段不需要依賴mysql-jdbc猾漫,如果同時我們希望將mysql-jdbc打包到lib中,以供運行階段使用感凤,則需要將該依賴聲明為runtime悯周。

provided適用的場景:依賴在編譯階段需要,但是我們不希望將該依賴打包到lib中陪竿,因為執(zhí)行的容器已經(jīng)提供了該jar包禽翼,如果我們重復提供可能會引起jar包沖突,比如打包flink任務的jar包時,flink相關的依賴闰挡,引擎已經(jīng)提供了仇矾,就不需要也不應該打包進去。

system可以認為和provided一致解总,只是必需要額外指定一個本地路徑,這個一般不推薦使用姐仅。

test適用的場景很單一花枫,如果一個依賴只是和測試代碼相關的,主代碼不使用掏膏,那就就聲明為test劳翰,該依賴在編譯和打包時都會忽略。

Maven中的依賴傳遞

首先要明確的是依賴傳遞解決的是什么問題馒疹,場景如下:

項目A依賴項目B佳簸,項目B依賴項目C,寫作A->B颖变,B->C

那么項目A對項目C的依賴關系是怎樣的生均?這就是依賴傳遞要解決的問題。

依賴傳遞的復雜性主要體現(xiàn)在不同scope下的表現(xiàn)不同腥刹,如圖所示:

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

image-20210717183403288

上表中左側的列是外層依賴(A->B)的scope马胧,第一行是內(nèi)層依賴(B->C)的scope,那么A->C的依賴結果為交叉點的結果衔峰。

結果說明:“-”表示不依賴佩脊,不依賴的結果是:A項目在編譯、測試垫卤、打包時都不能訪問C項目威彰。

上表有幾個典型的規(guī)律:

1.provided/test的依賴一定不會傳遞到外層

2.compile的依賴傳遞到外層時和外層的依賴scope相同

3.runtime的依賴傳遞到外層時和外層的依賴scope相同,除非外層是compile穴肘,會保持runtime

上述的規(guī)律還不足以明確地指導我們的使用歇盼,我們從具體的場景進行分析,分為兩類問題:

  • 問題一:如果我是A的開發(fā)梢褐,當我聲明A->B的scope時旺遮,對A->C的依賴有什么影響?
  • 問題二:如果我是B的開發(fā)盈咳,當我聲明B->C的scope時耿眉,對A->C的依賴有什么影響?

問題一:

最常見的場景鱼响,我聲明了A->B為compile鸣剪,這已經(jīng)是對B最強的依賴了,對于B內(nèi)部的依賴C

  • 如果是compile,會將compile傳遞出來筐骇,C在我的編譯和打包階段都會生效

  • 如果是runtime债鸡,那我對C的依賴也是runtime,編譯階段我不能使用C了铛纬,畢竟B也不能用厌均,我對B的內(nèi)部的C權限也不能更高,這一點符合直覺告唆;在打包時棺弊,C會打包到lib包中,這個需求是顯然的擒悬,否則很可能B項目運行階段會報錯模她。

    那么我可以將C聲明為provided嗎?可以懂牧,只要我確信這個包在運行時會提供侈净,這樣帶來的好處是可以避免jar包沖突,這樣引入了一個技巧僧凤,為了避免C的jar包沖突畜侦,除了到每一個B依賴中排除掉依賴之外,也可以在A項目中躯保,顯示聲明C為provided夏伊,這樣更加簡潔高效一些

  • 如果是provided或者test,我應當清楚吻氧,我不會對C有依賴

第二個場景溺忧,我聲明了A->B為provided,B不會打入我的jar包盯孙,而運行時會提供B的jar包鲁森,對于B內(nèi)部的依賴C

  • 如果是compile,此時我對C的依賴為provided振惰,即我可以編譯階段使用C歌溉,但C也不會打入我的jar包。
  • 如果是runtime骑晶,我對C的依賴變成了provided痛垛,在編譯階段看來,這似乎是一種強化桶蛔,B不能直接使用C的類匙头,我卻可以了;在打包階段看來仔雷,被弱化了蹂析,我不會將C打入自己的jar包舔示,這一點與外層B的provided是一致的
  • 如果是provided或者test,我應當清楚电抚,我不會對C有依賴

第三個場景惕稻,我聲明了A->B為runtime,B會打入我的jar包蝙叛,對于B內(nèi)部的依賴C俺祠,編譯階段我一定不能使用,畢竟B我都不能使用借帘,這一點是符合直覺的锻煌;那么打包階段呢,我會將compile和runtime的C打入jar包姻蚓,忽略provided和test

第四個場景,我聲明了A->B為test匣沼,同樣B的provide和test不會被我訪問到狰挡,但是B的compile和runtime依賴我可以在測試中自由使用,這里runtime似乎也升級了

問題二:

最常見的場景释涛,我聲明了B->C為compile加叁,因為我對C的依賴是足夠強的,我會期望外部對我的依賴scope也會透傳到對C的依賴唇撬。

第二個場景它匕,我聲明了B->C為provided或test,這意味著外界對C完全不可見窖认,不能編譯豫柬,也不會打包自己的項目。

第三個場景扑浸,我聲明了B->C為runtime烧给,外部對我的依賴scope也會透傳到對C的依賴,這個其實是不太安全的喝噪,這個時候我會發(fā)現(xiàn)我編譯階段不能依賴的C础嫡,外部反而可以了,這個時候我對投傳下來的compile降級為runtime酝惧,其他的未做處理榴鼎。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市晚唇,隨后出現(xiàn)的幾起案子巫财,更是在濱河造成了極大的恐慌,老刑警劉巖哩陕,帶你破解...
    沈念sama閱讀 218,525評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翁涤,死亡現(xiàn)場離奇詭異桥言,居然都是意外死亡,警方通過查閱死者的電腦和手機葵礼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評論 3 395
  • 文/潘曉璐 我一進店門号阿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人鸳粉,你說我怎么就攤上這事扔涧。” “怎么了届谈?”我有些...
    開封第一講書人閱讀 164,862評論 0 354
  • 文/不壞的土叔 我叫張陵枯夜,是天一觀的道長。 經(jīng)常有香客問我艰山,道長湖雹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評論 1 294
  • 正文 為了忘掉前任曙搬,我火速辦了婚禮摔吏,結果婚禮上,老公的妹妹穿的比我還像新娘纵装。我一直安慰自己征讲,他們只是感情好,可當我...
    茶點故事閱讀 67,743評論 6 392
  • 文/花漫 我一把揭開白布橡娄。 她就那樣靜靜地躺著诗箍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪挽唉。 梳的紋絲不亂的頭發(fā)上滤祖,一...
    開封第一講書人閱讀 51,590評論 1 305
  • 那天,我揣著相機與錄音瓶籽,去河邊找鬼氨距。 笑死,一個胖子當著我的面吹牛棘劣,可吹牛的內(nèi)容都是我干的俏让。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼茬暇,長吁一口氣:“原來是場噩夢啊……” “哼首昔!你這毒婦竟也來了?” 一聲冷哼從身側響起糙俗,我...
    開封第一講書人閱讀 39,244評論 0 276
  • 序言:老撾萬榮一對情侶失蹤勒奇,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巧骚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赊颠,經(jīng)...
    沈念sama閱讀 45,693評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡格二,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,885評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了竣蹦。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顶猜。...
    茶點故事閱讀 40,001評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖痘括,靈堂內(nèi)的尸體忽然破棺而出长窄,到底是詐尸還是另有隱情,我是刑警寧澤纲菌,帶...
    沈念sama閱讀 35,723評論 5 346
  • 正文 年R本政府宣布挠日,位于F島的核電站塘娶,受9級特大地震影響睛驳,放射性物質(zhì)發(fā)生泄漏搓逾。R本人自食惡果不足惜涨冀,卻給世界環(huán)境...
    茶點故事閱讀 41,343評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怀跛。 院中可真熱鬧漓藕,春花似錦茸习、人聲如沸夜涕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽女器。三九已至,卻和暖如春住诸,著一層夾襖步出監(jiān)牢的瞬間驾胆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評論 1 270
  • 我被黑心中介騙來泰國打工贱呐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丧诺,地道東北人。 一個月前我還...
    沈念sama閱讀 48,191評論 3 370
  • 正文 我出身青樓奄薇,卻偏偏與公主長得像驳阎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子馁蒂,可洞房花燭夜當晚...
    茶點故事閱讀 44,955評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1.Maven介紹 Maven是一個基于項目對象模型(POM)的概念的純java開發(fā)的開源的項目管理工具呵晚。主要用來...
    蒲公英愛上閱讀 1,090評論 0 0
  • 問題背景 公司有個業(yè)務功能的組件,該組件以jar包的形式透出去沫屡;為了把組件的pom弄的比較干凈饵隙,一開始沒有加入任何...
    ericsonyc閱讀 263評論 0 0
  • Dependency Scope 在POM 4中,<dependency>中還引入了 沮脖,它主要管理依賴的部署金矛。目前...
    MakeACoder閱讀 423評論 0 0
  • maven項目中需要使用到其它依賴時芯急,則需要在pom.xml中配置<dependency>元素也就是依賴聲明,這樣...
    zlcook閱讀 1,821評論 1 3
  • Maven依賴中scope的含義 整理一下Maven中Scope的詳細作用驶俊,都是抄的別人內(nèi)容整理了一下娶耍。參考:ht...
    UEUEO閱讀 34,531評論 7 33