maven依賴沖突加載順序與解決
依賴沖突加載順序
介紹了項(xiàng)目中同時(shí)引用了相同依賴的不同版本,也就是沖突,maven 是如何選擇的。了解了有助于解決項(xiàng)目中的依賴問題
先說結(jié)論:
- 直接依賴的會(huì)引用后申明的依賴
- 間接依賴使用路徑長度最短的,如果長度一樣,則優(yōu)先申明的最終加載
- 有父 pom 的子 pom 中的會(huì)覆蓋父 pom 的依賴版本
<dependencyManagement>管理的版本,子模塊 pom 中間接依賴的版本也被鎖死
優(yōu)先級(jí)(運(yùn)行子 pom):<dependencyManagement> > 子 pom(直接依賴) > 父 pom > 間接依賴
直接依賴
<!-- 直接依賴 -->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.19.4</version>
</dependency>

項(xiàng)目的 pom 文件直接引用依賴
結(jié)論:maven 會(huì)引用后申明的依賴
- 這種情況幾乎不會(huì)有,誰會(huì)在一處同時(shí)申明2個(gè)相同依賴不同版本的依賴,假使出現(xiàn)了,了解即可。
間接依賴
假設(shè) module-starter 的 pom 如下:
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module4</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module1</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

module4 引用 protobuf-java:3.11.4
module1 引用 protobuf-java:2.2.0
最終使用的是 protobuf-java:3.11.4
結(jié)論:間接依賴使用優(yōu)先申明的
假設(shè) module-starter 的 pom 如下:
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module2</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module4</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

module4 引用 protobuf-java:3.11.4 (路徑長度1)
module2 引用 module3 引用 protobuf-java:3.19.4(路徑長度2)
最終使用的是 protobuf-java:3.11.4
結(jié)論:間接依賴使用路徑長度最短的,如果長度一樣,則優(yōu)先申明的最終加載
父 pom 中的依賴
父 pom 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.meizi</groupId>
<artifactId>learnmaven</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>module1</module>
<module>module2</module>
<module>module3</module>
<module>module4</module>
<module>module-starter</module>
</modules>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.4</version>
</dependency>
</dependencies>
</project>
module1 pom 如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>learnmaven</artifactId>
<groupId>com.meizi</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>module1</artifactId>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</project>

結(jié)論:子 pom 中的會(huì)覆蓋父 pom 的依賴版本
- 如果間接依賴和父 pom 中的依賴出現(xiàn),以父 pom 優(yōu)先
版本鎖定 <dependencyManagement>
使用
如下在父 pom 申明:
<!-- learnmaven 父pom-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
</dependencyManagement>
子模塊 pom 可不用寫版本
子模塊中與 dependencyManagement 匹配的最小信息集是這四個(gè) {groupId, artifactId, type, classifier},因?yàn)樵诖蠖鄶?shù)情況下都是 type=jar classifier=null,所以如果不寫,maven默認(rèn),如果不是jar的需要指定。
<!-- module-starter 子pom-->
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
子模塊 pom 中間接依賴的版本也被鎖死
<!-- module-starter 子pom-->
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module4</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module3</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

從可傳播依賴并入的依賴的版本也受此限制。
依賴沖突解決
了解了依賴沖突加載順序,一定程度上可以解決沖突。 由于沒有依賴傳播級(jí)數(shù)的限制,會(huì)有可能出現(xiàn)循環(huán)依賴。 所以有一些方式來限制依賴傳播
依賴調(diào)解(最短路徑)
最短路徑 項(xiàng)目的依賴樹最近的依賴
如下依賴:
A
├── B
│ └── C
│ └── D 2.0
└── E
└── D 1.0
會(huì)使用 D 1.0,因?yàn)樗穆窂阶疃?,如果你想使?nbsp;D 2.0 可以在 A 項(xiàng)目中直接添加 D 2.0 依賴,如下
A ├── B │ └── C │ └── D 2.0 ├── E │ └── D 1.0 │ └── D 2.0
版本鎖定
即 <dependencyManagement>,使用見上文
依賴作用域
即 <scope> 作用域,限制依賴傳遞和決定何時(shí)依賴包含在類路徑中
提供如下選項(xiàng):
- compile 默認(rèn),編譯依賴項(xiàng)在項(xiàng)目的所有類路徑中都可用。此外,這些依賴關(guān)系被傳播到依賴的項(xiàng)目。
- runtime 在編譯中不需要,在執(zhí)行中需要
- test 表明該依賴在正常使用中不是必須的,并且僅在測(cè)試編譯和執(zhí)行階段可用,這個(gè)作用域不是可傳遞的
- system 除了您必須提供顯式包含它的JAR之外,此作用域與提供的作用域類似。工件總是可用的,不會(huì)在存儲(chǔ)庫中查找。
- provided 類似compile,表明這個(gè)依賴是提供的,在運(yùn)行時(shí)會(huì)有外部提供(例如tomcat),僅在編譯和測(cè)試,是不可傳遞的
- import 只用在pom的
<dependencyManagement>部分,它指示該依賴項(xiàng)將被指定POM的<dependencyManagement>部分中的有效依賴項(xiàng)列表所替換。
排除依賴
通過使用 exclusion 可以將不需要的依賴排除掉
<dependency>
<groupId>com.meizi</groupId>
<artifactId>module4</artifactId>
<version>1.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</exclusion>
</exclusions>
</dependency>
此時(shí),引入module4,將不會(huì)引入 protobuf-java。
可選依賴
即 <optional>,默認(rèn)false不可選,可傳播; true 可選,可認(rèn)為是被排除了,不可傳播
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>3.11.4</version>
<!-- 默認(rèn)false不可選,可傳播; true 可選,可認(rèn)為是被排除了,不可傳播 -->
<optional>true</optional>
</dependency>
如果想排除此依賴,也可將 optional 設(shè)置為 true
依賴管理
導(dǎo)入依賴
在大型項(xiàng)目中,很難通過繼承管理所有依賴,因?yàn)?maven 是單繼承的。
為了解決這個(gè),項(xiàng)目可以從其他項(xiàng)目導(dǎo)入。通過申明一個(gè) type 是 pom,scope 是 import 的工件
<!-- learnmaven 父pom-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>4.1.29.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
所有 netty-bom 中 dependencyManagement 所管理的都會(huì)被合并過來。
<!-- learnmaven 父pom-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>4.1.79.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-bom</artifactId>
<version>4.1.29.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
如上,4.1.79.Final 將被使用,因?yàn)樗壬昝?br />并且導(dǎo)入是遞歸的,例如,netty-bom 導(dǎo)入了另一個(gè) pom,那么這個(gè)項(xiàng)目也會(huì)導(dǎo)入
到此這篇關(guān)于maven依賴沖突加載順序與解決的文章就介紹到這了,更多相關(guān)maven依賴沖突內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java訪問Hadoop分布式文件系統(tǒng)HDFS的配置說明
Hadoop的能提供高吞吐量的數(shù)據(jù)訪問,是集群式服務(wù)器的上的數(shù)據(jù)操作利器,這里就來為大家分享Java訪問Hadoop分布式文件系統(tǒng)HDFS的配置說明:2016-06-06
java?啟動(dòng)參數(shù)?springboot?idea詳解
這篇文章主要介紹了java?啟動(dòng)參數(shù)?springboot?idea的相關(guān)知識(shí),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09
關(guān)于mybatis的一級(jí)緩存和二級(jí)緩存的那些事兒
MyBatis自帶的緩存有一級(jí)緩存和二級(jí)緩存,今天我們就來學(xué)習(xí)一下,文中有非常詳細(xì)的總結(jié),對(duì)正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06
SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表
這篇文章主要介紹了SpringBoot+jpa配置如何根據(jù)實(shí)體類自動(dòng)創(chuàng)建表,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
Netty分布式抽象編碼器MessageToByteEncoder邏輯分析
這篇文章主要介紹了Netty分布式抽象編碼器MessageToByteEncoder的抽象邏輯分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03

