Java包管理以及Maven包管理

眾所周知,Java包管理是學(xué)習(xí)Java過(guò)程中一個(gè)很重要的內(nèi)容温圆。本篇文章將著重介紹Java包管理以及Maven包管理的原理麻敌,以及解決包沖突的方法。

JVM工作原理

首先帘不,我們先來(lái)了解一下JVM的工作原理说莫,其實(shí)簡(jiǎn)單地概括性地說(shuō),JVM只會(huì)做兩件事情:

  1. 執(zhí)行一個(gè)類(lèi)的字節(jié)碼
  2. 在執(zhí)行這個(gè)類(lèi)的字節(jié)碼的時(shí)候寞焙,若碰到了新的類(lèi)储狭,則加載它
  3. 不斷重復(fù)以上兩個(gè)過(guò)程

可見(jiàn)互婿,JVM的工作是如此的簡(jiǎn)單和枯燥,但讀到這里的你辽狈,可能會(huì)產(chǎn)生一個(gè)問(wèn)題慈参,JVM是怎么知道在哪里讀取這些類(lèi)的呢?
針對(duì)這個(gè)問(wèn)題刮萌,我也不賣(mài)關(guān)子了懂牧,直接告訴你答案,JVM是通過(guò)classpath參數(shù)來(lái)獲取到這個(gè)路徑的尊勿。
那么新的問(wèn)題又出現(xiàn)了僧凤,我明明沒(méi)有給JVM傳遞這個(gè)參數(shù)呀,它是怎么獲取到的呢元扔?

是的躯保,沒(méi)錯(cuò),你沒(méi)有給JVM傳遞classpath這個(gè)參數(shù)澎语,但是你的編譯器偷偷幫你干了這件事情了途事!

(不相信的話(huà),每次用編譯器編譯的時(shí)候擅羞,控制臺(tái)都會(huì)有一串命令尸变,在命令里面你可以清楚地看到編譯器給JVM偷偷傳遞了classpath參數(shù))

給JVM傳遞classpath參數(shù)
給JVM傳遞classpath參數(shù)

另外,由于一個(gè)包有可能又依賴(lài)于其他很多個(gè)包减俏,因此一個(gè)項(xiàng)目下來(lái)召烂,可能classpath下的依賴(lài)路徑會(huì)變得又臭又長(zhǎng)。
在Java剛誕生的時(shí)候娃承,人們是需要通過(guò)手寫(xiě)這些classpath路徑來(lái)讓JVM讀懂讀取jar包(一堆類(lèi)的集合)的路徑的奏夫,后面再人們的不斷努力下,強(qiáng)大的IDEA和Maven的誕生历筝,才讓這個(gè)繁瑣的過(guò)程變得無(wú)比簡(jiǎn)單酗昼。

依賴(lài)地獄

在Maven誕生之前,依賴(lài)沖突是一個(gè)很容易發(fā)生且很難解決的問(wèn)題梳猪,我們把這種依賴(lài)沖突又稱(chēng)為classpath hell(依賴(lài)地獄)麻削。
什么是依賴(lài)沖突,由于全限定類(lèi)名是類(lèi)的唯一標(biāo)示春弥,因此當(dāng)多個(gè)同名類(lèi)不同版本同時(shí)出現(xiàn)在classpath的時(shí)候呛哟,就是噩夢(mèng)的開(kāi)始。

依賴(lài)沖突
依賴(lài)沖突

如上圖惕稻,A包依賴(lài)了B包和C2包竖共,而B(niǎo)包又依賴(lài)了C1包,在這個(gè)時(shí)候俺祠,由于所有的依賴(lài)包的路徑都會(huì)寫(xiě)在classpath上面公给,讓JVM從前往后地在這些路徑上面尋早需要的依賴(lài)包借帘,因此,若JVM先讀取到了C1依賴(lài)包的classpath路徑淌铐,那么C2這個(gè)依賴(lài)包肺然,由于和C1只是版本上面的不同,因此JVM會(huì)誤把C1路徑中找到的依賴(lài)包也同樣作用在C2上面腿准,從而導(dǎo)致出現(xiàn)不可預(yù)期的錯(cuò)誤际起。

一般來(lái)說(shuō),當(dāng)你看到你的代碼在編譯運(yùn)行之后吐葱,出現(xiàn)了以下的錯(cuò)誤街望,那就代表最麻煩的包沖突出現(xiàn)了:

  1. AbstractMethodError
  2. NoClassDefFoundError
  3. ClassNotFoundException
  4. LinkageError

Maven包管理的原理

在Maven沒(méi)有誕生之前,包沖突只能通過(guò)手動(dòng)尋找沖突的包依賴(lài)弟跑,并把對(duì)應(yīng)的包進(jìn)行升級(jí)或者替換灾前,但問(wèn)題是,一個(gè)項(xiàng)目一般存在著很多很多的包依賴(lài)孟辑,手動(dòng)尋找費(fèi)時(shí)費(fèi)力哎甲,效率太低。直到后來(lái)Maven的誕生饲嗽,才使得解決包依賴(lài)的解決變得不再那么麻煩炭玫。

首先我們先來(lái)了解一下Maven是如何對(duì)包進(jìn)行管理的
我們需要首先知道的是,Maven有一套約定俗成的規(guī)范貌虾,其中規(guī)定了吞加,生產(chǎn)代碼需要放在src/main目錄下面,而測(cè)試代碼則需要放在test/main目錄下面酝惧。這個(gè)將在之后講包管理的scope中有用榴鼎。

Maven會(huì)有中央倉(cāng)庫(kù)和本地倉(cāng)庫(kù)兩個(gè)倉(cāng)庫(kù)
本地倉(cāng)庫(kù)即字面意思在本地你電腦中存在的倉(cāng)庫(kù),它默認(rèn)位于~/.m2目錄中晚唇,里面會(huì)放置一些經(jīng)過(guò)下載的第三方包的緩存。
而中央倉(cāng)庫(kù)即線(xiàn)上倉(cāng)庫(kù)的意思盗似,一個(gè)包會(huì)含有groupId哩陕、artifactIdversion三個(gè)字段赫舒,因此在中央倉(cāng)庫(kù)中悍及,一個(gè)包存放的路徑也是以這三個(gè)字段來(lái)存放的,具體會(huì)存放在groupId/artifactId/version這個(gè)位置接癌。

當(dāng)一個(gè)項(xiàng)目需要使用一些第三方包的時(shí)候心赶,你可以在pom文件中添加這些包的信息,這樣Maven就會(huì)自動(dòng)幫你下載這些包以及其相關(guān)依賴(lài)包到本地中緩存起來(lái)缺猛,具體的添加方式如下圖所示:

pom文件
pom文件


如何解決包沖突

好了缨叫,說(shuō)到這里椭符,相信你已經(jīng)基本了解了Maven是如何對(duì)第三方包進(jìn)行管理的了,接下來(lái)耻姥,我們就來(lái)講一下Maven是如何解決包沖突的销钝。
首先我們需要知道解決包沖突的一個(gè)原則:絕對(duì)不允許最終的classpath出現(xiàn)同名不同版本的jar包

在Maven中,當(dāng)出現(xiàn)包沖突的問(wèn)題的時(shí)候琐簇,Maven會(huì)保留離項(xiàng)目最近的包蒸健,而去除其他有沖突的包,拿之前的例子來(lái)說(shuō):
解決依賴(lài)沖突
解決依賴(lài)沖突

相比于C1來(lái)說(shuō)婉商,C2這個(gè)第三方包離項(xiàng)目更接近似忧,因此Maven會(huì)自動(dòng)幫你把C1去除,而保留C2丈秩。但是這種策略有時(shí)候是不完美的盯捌,因此有時(shí)候也需要我們?nèi)藶榈厝ゾS護(hù)它,但不管怎么說(shuō)癣籽,由于Maven的誕生挽唉,使得我們對(duì)于第三方包的很多操作都變得輕松和簡(jiǎn)單了。

接下來(lái)我們來(lái)說(shuō)一下人為解決沖突的三種辦法:

  1. 直接依賴(lài)高版本依賴(lài)筷狼,這樣Maven就能去除所有低版本的不合適的依賴(lài)了瓶籽,具體來(lái)說(shuō)如下所示:
解決依賴(lài)沖突
解決依賴(lài)沖突

C1、C2和C3三個(gè)版本沖突了埂材,但我們只要直接依賴(lài)了最高版本C3塑顺,把它作為項(xiàng)目的直接依賴(lài),這樣C1俏险、C2這兩個(gè)不合適的第三方包就會(huì)自動(dòng)被Maven去除掉严拒,從而解決了沖突。

  1. 通過(guò)pom文件來(lái)排除包中的后代指定依賴(lài)

具體操作如以下代碼所示:

<dependency>
  <groupId>xxx</groupId>
  <artifactId>xxx</artifactId>
  <version>1.0.0</version>
  <exclusions>
    <exclusion>
        <groupId>yyy</groupId>
      <artifactId>yyy</artifactId>
    </exclusion>
  </exclusions>
</dependency>

通過(guò)以上的代碼竖独,即可排除了xxx依賴(lài)中的后代yyy依賴(lài)裤唠,也可以解決包沖突的問(wèn)題

3.通過(guò)Maven helper插件來(lái)解決包沖突問(wèn)題,由于這個(gè)是工具性的操作莹痢,因此這里不過(guò)多介紹种蘸,大家可以自行去嘗試。

最后竞膳,說(shuō)一下pom文件中航瞭,可以通過(guò)設(shè)置scope標(biāo)簽,來(lái)指定一個(gè)包是否可以被生產(chǎn)代碼和測(cè)試代碼所引用:

  1. complie(生產(chǎn)代碼以及測(cè)試代碼均可見(jiàn))
  2. test(只有測(cè)試代碼可見(jiàn))
  3. provided(只在編譯的生產(chǎn)代碼的時(shí)候生效坦辟,在運(yùn)行時(shí)無(wú)效)

以上刊侯,就是本篇文章的所有內(nèi)容,謝謝閱讀~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锉走,一起剝皮案震驚了整個(gè)濱河市滨彻,隨后出現(xiàn)的幾起案子藕届,更是在濱河造成了極大的恐慌,老刑警劉巖疮绷,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翰舌,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡冬骚,警方通過(guò)查閱死者的電腦和手機(jī)椅贱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)只冻,“玉大人庇麦,你說(shuō)我怎么就攤上這事∠驳拢” “怎么了山橄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)舍悯。 經(jīng)常有香客問(wèn)我航棱,道長(zhǎng),這世上最難降的妖魔是什么萌衬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任饮醇,我火速辦了婚禮,結(jié)果婚禮上秕豫,老公的妹妹穿的比我還像新娘朴艰。我一直安慰自己,他們只是感情好混移,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布祠墅。 她就那樣靜靜地躺著,像睡著了一般歌径。 火紅的嫁衣襯著肌膚如雪毁嗦。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天回铛,我揣著相機(jī)與錄音金矛,去河邊找鬼。 笑死勺届,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娶耍。 我是一名探鬼主播免姿,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼榕酒!你這毒婦竟也來(lái)了胚膊?” 一聲冷哼從身側(cè)響起故俐,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎紊婉,沒(méi)想到半個(gè)月后药版,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡喻犁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年槽片,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肢础。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡还栓,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出传轰,到底是詐尸還是另有隱情剩盒,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布慨蛙,位于F島的核電站辽聊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏期贫。R本人自食惡果不足惜跟匆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望唯灵。 院中可真熱鬧贾铝,春花似錦、人聲如沸埠帕。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)敛瓷。三九已至叁巨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呐籽,已是汗流浹背锋勺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留狡蝶,地道東北人庶橱。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像贪惹,于是被迫代替她去往敵國(guó)和親苏章。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345