Maven直接依賴、間接依賴、依賴沖突、依賴仲裁的實(shí)現(xiàn)
直接依賴和間接依賴
在項(xiàng)目中直接引入的依賴叫做直接依賴,而那些被動(dòng)引入的就叫間接依賴

比如上圖中,A 是我們的項(xiàng)目,我們?cè)陧?xiàng)目中直接引入了 B 模塊,所以 B 和 A 的關(guān)系就是直接依賴,而 B 工程內(nèi)部引入了 C,所以 B 和 C 也是直接依賴關(guān)系,如果 B 工程在引入 C 時(shí),指定了 C 模塊的依賴范圍是 <scope>compile</scope> ,那么 C 模塊就會(huì)隨著 B 模塊一同被引入到我們的工程A 中,這時(shí)候 A 和 C 的關(guān)系就是間接依賴
依賴沖突
Maven 的依賴沖突,我認(rèn)為有兩種情況,Maven 能自動(dòng)解決的、需要手動(dòng)解決的
1. Maven 可以自動(dòng)解決的依賴沖突
在項(xiàng)目中,不管是直接依賴還是間接依賴,當(dāng)有多個(gè) <groupId> 、 <artifactId> 相同, <version> 不同的依賴引入時(shí),Maven 就會(huì)認(rèn)為我們引入了相同模塊的不同版本,其就會(huì)被判定為依賴沖突,這種情況 Maven 會(huì)用自己的仲裁機(jī)制幫我們?nèi)∩?/p>
2. 需要手動(dòng)解決的依賴沖突
模塊間的 <groupId> 、 <artifactId> 、 <version> 都不相同,但是引入的這些模塊中具有相同路徑的類(包名+類名完全相同),這個(gè)時(shí)候就需要我們自己去解決依賴沖突問題
Maven 的依賴仲裁
依賴仲裁是 Maven 自動(dòng)解決依賴沖突的手段,我們想更好的利用它,就必須知道其仲裁的規(guī)則,其通過 最短路徑優(yōu)先 和 先聲明優(yōu)先 兩個(gè)依據(jù)來判斷最終留下的模塊
最短路徑優(yōu)先
當(dāng)項(xiàng)目的依賴樹中存在相同模塊的不同版本時(shí),Maven 的仲裁機(jī)制就會(huì)介入,其首先會(huì)通過最短路徑的方式來對(duì)沖突的模塊進(jìn)行取舍,如下圖,假設(shè)我們的項(xiàng)目是A,明顯C模塊發(fā)生了依賴沖突,那么按照最短路徑優(yōu)先的原則,Maven 最后會(huì)留下 A → B → C 1.0 這個(gè)路徑下的 C 模塊

先聲明優(yōu)先
當(dāng)兩個(gè)依賴沖突的模塊,其路徑距離相同時(shí),就會(huì)使用先聲明優(yōu)先的規(guī)則,這個(gè)就很簡(jiǎn)單了,就是留下先聲明的模塊,如下圖,假設(shè)我們的項(xiàng)目是A,兩個(gè)沖突的模塊C到 A 的距離是相同的,這時(shí) Maven 就會(huì)根據(jù)先聲明優(yōu)先的規(guī)則選擇A → B → C 1.0 這個(gè)路徑下的 C 模塊,因?yàn)槠渎暶髟谇?/p>

至于什么叫先聲明,非常簡(jiǎn)單,用上圖例子,我寫個(gè)偽代碼
<!-- 這個(gè) B 的依賴信息就是先聲明的,所以仲裁后會(huì)留下B模塊中依賴的C模塊 -->
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>release</version>
</dependency>
<dependency>
<groupId>D</groupId>
<artifactId>D</artifactId>
<version>release</version>
</dependency>了解仲裁規(guī)則后,也可以利用 Maven 的仲裁規(guī)則,保留自己想要的模塊,比如上面例子中,我們想保留模塊 C 2.0,那么就可以將模塊 C 2.0 的依賴信息主動(dòng)聲明在依賴列表的最前面,這樣不論是最短路徑規(guī)則還是先聲明的規(guī)則,都會(huì)判定 C 2.0 被保留,偽代碼如下:
<!--在依賴列表的最前面主動(dòng)聲明模塊C2.0的依賴信息-->
<dependency>
<groupId>C</groupId>
<artifactId>C</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>B</groupId>
<artifactId>B</artifactId>
<version>release</version>
</dependency>
<dependency>
<groupId>D</groupId>
<artifactId>D</artifactId>
<version>release</version>
</dependency>手動(dòng)解決依賴沖突
需要手動(dòng)解決的情況,是指不同模塊中,具有相同路徑的類(包名和類名完全相同),從而導(dǎo)致項(xiàng)目啟動(dòng)后,類加載器加載了同名的非目標(biāo)類,從而出現(xiàn) ClassNotFoundException 、 NoClassDefFoundError 、 LinkageError 等類似的錯(cuò)誤
手動(dòng)解決依賴沖突,首先需要找出路徑相同的類所在的模塊,其次決定要留用的模塊
找出類路徑相同的模塊
可以借助 Maven 的生命周期插件 maven-enforcer-plugin
1. 在項(xiàng)目的 Pom.xml 中添加配置
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<executions>
<execution>
<id>enforce-dependencies</id>
<phase>validate</phase>
<goals>
<goal>display-info</goal>
<goal>enforce</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo</groupId>
<artifactId>extra-enforcer-rules</artifactId>
<version>1.0-beta-4</version>
</dependency>
</dependencies>
<configuration>
<rules>
<banDuplicateClasses>
<findAllDuplicates>true</findAllDuplicates>
</banDuplicateClasses>
</rules>
</configuration>
</plugin>
</plugins>
</build>(2) 執(zhí)行 mvn clean package enforcer:enforce 命令后,就能看見重復(fù)的類和模塊

(3) 找到?jīng)_突的模塊后,刪掉棄用的模塊,如果是直接依賴的模塊直接刪除依賴信息就好,如果是間接依賴的模塊,就要使用 <exclusions> 排除依賴傳遞,方式如下:
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<!-- 排除依賴傳遞 -->
<exclusions>
<exclusion>
<groupId>要棄用的模塊的groupId</groupId>
<artifactId>要棄用的模塊的artifactId</artifactId>
</exclusion>
</exclusions>
</dependency>到此這篇關(guān)于Maven直接依賴、間接依賴、依賴沖突、依賴仲裁的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Maven直接依賴、間接依賴、依賴沖突、依賴仲裁內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot集成FastDFS實(shí)現(xiàn)防盜鏈功能
FastDFS是一個(gè)高性能的分布式?件系統(tǒng),本文將為大家詳細(xì)介紹一下SpringBoot如何集成FastDFS實(shí)現(xiàn)防盜鏈功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-04-04
解決?IDEA?Maven?項(xiàng)目中"Could?not?find?artifact"?
這篇文章主要介紹了解決IDEA Maven項(xiàng)目中Could not?find?artifact問題的常見情況和解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-07-07
spring整合redis以及使用RedisTemplate的方法
本篇文章主要介紹了spring整合redis以及使用RedisTemplate的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05
利用Java實(shí)現(xiàn)word導(dǎo)入導(dǎo)出富文本(含圖片)的詳細(xì)代碼
這篇文章主要為大家詳細(xì)介紹了利用Java實(shí)現(xiàn)word導(dǎo)入導(dǎo)出富文本(含圖片),文中的示例代碼講解詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以學(xué)習(xí)一下2024-02-02
Java設(shè)計(jì)模式之原型模式詳細(xì)解析
這篇文章主要介紹了Java設(shè)計(jì)模式之原型模式詳細(xì)解析,原型模式就是用一個(gè)已經(jīng)創(chuàng)建的實(shí)例作為原型,通過復(fù)制該原型對(duì)象來創(chuàng)建一個(gè)和原型對(duì)象相同的新對(duì)象,需要的朋友可以參考下2023-11-11
MyBatis如何使用PageHelper實(shí)現(xiàn)分頁查詢
這篇文章主要介紹了MyBatis如何使用PageHelper實(shí)現(xiàn)分頁查詢,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Mybatis聯(lián)合查詢的實(shí)現(xiàn)方法
本文主要介紹了 Mybatis聯(lián)合查詢的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
SpringBoot隨機(jī)端口啟動(dòng)的實(shí)現(xiàn)
本文主要介紹了SpringBoot隨機(jī)端口啟動(dòng)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-07-07
Spring Boot中使用Actuator的/info端點(diǎn)輸出Git版本信息
這篇文章主要介紹了Spring Boot中使用Actuator的/info端點(diǎn)輸出Git版本信息,需要的朋友可以參考下2017-06-06

