項(xiàng)目開發(fā)過程中經(jīng)常會(huì)碰到maven依賴沖突的問題,這篇post整理下maven依賴沖突產(chǎn)生的原因以及解決方案
maven依賴沖突的產(chǎn)生是由maven傳遞性依賴造成的:
什么是maven傳遞依賴?
“一個(gè)傳遞性依賴就是對于一個(gè)依賴的依賴。如果project-a依賴于project-b,而后
者接著依賴于project-c,那么project-c就被認(rèn)為是project-a的傳遞性依賴。如
果project-c依賴于project-d,那么project-d就也被認(rèn)為是project-a的傳遞性依
賴。Maven的部分吸引力是由于它能夠管理傳遞性依賴,并且能夠幫助開發(fā)者屏蔽掉跟
蹤所有編譯期和運(yùn)行期依賴的細(xì)節(jié)。你可以只依賴于一些包如Spring Framework,而不
用擔(dān)心Spring Framework的所有依賴,Maven幫你自動(dòng)管理了,你不用自己去詳細(xì)了解
配置。
Maven是怎樣完成這件事情的呢?它建立一個(gè)依賴圖,并且處理一些可能發(fā)生的沖突和
重疊。例如,如果Maven看到有兩個(gè)項(xiàng)目依賴于同樣的groupId和artifactId,它會(huì)自動(dòng)
整理出使用哪個(gè)依賴,選擇那個(gè)最新版本的依賴。雖然這聽起來很方便,但在一些邊界
情況中,傳遞性依賴會(huì)造成一些配置問題。在這種情況下,你可以使用依賴排除。”
——摘自《Maven權(quán)威指南》
什么情況下會(huì)產(chǎn)生依賴沖突?
舉例說明:項(xiàng)目中的pom.xml里聲明了對project-a1.0與project-b2.0的依賴,而project-a1.0又傳遞依賴于project-b1.0的版本。
假設(shè)maven經(jīng)過分析之后決定使用project-b1.0的依賴,也就是打包的時(shí)候把project-b1.0.jar打進(jìn)了war包。
war包部署在java容器中啟動(dòng)之后,如果依賴project-b2.0.jar中新添的類或方法,就會(huì)發(fā)現(xiàn)引用的類或者方法不存在。
這種現(xiàn)象就是依賴沖突。
如何分析依賴沖突?
mvn dependency:tree
沖突解決方案:
使用maven提供的<exclusion>標(biāo)簽。
舉例說明:
如果你正依賴于一個(gè)類庫,該類庫又依賴于Sun JTA API,你會(huì)想要替換這個(gè)傳遞性依賴。
Hibernate是一個(gè)例子。Hibernate依賴于Sun JTA API,而后者在中央Maven倉庫中不可用,因?yàn)樗遣?br />能免費(fèi)分發(fā)的。幸運(yùn)的是,Apache Gernoimo項(xiàng)目創(chuàng)建了一些可以免費(fèi)分發(fā)的獨(dú)立實(shí)現(xiàn)
類庫。為了用另外的依賴來替換這個(gè)傳遞性依賴,你需要排除這個(gè)傳遞性以依賴,然后
在你的項(xiàng)目中再聲明一個(gè)依賴。下面展示了這樣一個(gè)替換的樣例。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.5.ga</version>
<exclusions>
<exclusion>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-jta_1.1_spec</artifactId>
<version>1.1</version>
</dependency>