管理包依賴是 Maven 核心功能之一私沮,下面通過(guò)如何引入 jar 包始赎;如何解析 jar 包依賴;包沖突是如何產(chǎn)生顾彰;如何解決包沖突极阅;依賴管理解決什么問(wèn)題;什么是依賴范圍涨享;使用包依賴的最佳實(shí)踐等 6 個(gè)問(wèn)題來(lái)介紹筋搏。
如何引入 jar 包
在代碼開(kāi)發(fā)時(shí),如果需要使用第三方 jar 包提供的類庫(kù)厕隧,那么需要在 pom.xml 加入該 jar 包依賴奔脐。
例如:使用 zookeeper client
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hadoop/zookeeper -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.1</version>
</dependency>
</dependencies>
Maven 如何解析 jar 包依賴——傳遞依賴
如上所述,在 pom.xml 中引入 zookeeper jar 包依賴吁讨,當(dāng) Maven 解析該依賴時(shí)髓迎,需要引入的 jar 包不僅僅只有 zookeeper,還會(huì)有 zookeeper 內(nèi)部依賴的 jar 包建丧,還會(huì)有 zookeeper 內(nèi)部依賴的 jar 包依賴的 jar 包......排龄,依賴關(guān)系不斷傳遞,直至沒(méi)有依賴翎朱。
例如:上述 pom.xml 引入 zookeeper 依賴橄维,實(shí)際引入的 jar 包有:
包沖突如何產(chǎn)生?
舉個(gè)??:假設(shè) A->B->C->D1, E->F->D2拴曲,D1,D2 分別為 D 的不同版本争舞。
如果 pom.xml 文件中引入了 A 和 E 之后,按照 Maven 傳遞依賴原則澈灼,工程內(nèi)需要引入的實(shí)際 Jar 包將會(huì)有:A B C D1 和 E F D2竞川,因此 D1,D2 將會(huì)產(chǎn)生包沖突。
如何解決包沖突
Maven 解析 pom.xml 文件時(shí)叁熔,同一個(gè) jar 包只會(huì)保留一個(gè)委乌,這樣有效的避免因引入兩個(gè) jar 包導(dǎo)致的工程運(yùn)行不穩(wěn)定性。
Maven 默認(rèn)處理策略
- 最短路徑優(yōu)先
Maven 面對(duì) D1 和 D2 時(shí)者疤,會(huì)默認(rèn)選擇最短路徑的那個(gè) jar 包福澡,即 D2。E->F->D2 比 A->B->C->D1 路徑短 1驹马。 - 最先聲明優(yōu)先
如果路徑一樣的話革砸,舉個(gè)??: A->B->C1, E->F->C2 ,兩個(gè)依賴路徑長(zhǎng)度都是 2糯累,那么就選擇最先聲明算利。
移除依賴
如果我們不想通過(guò) A->B->->D1 引入 D1 的話,那么我們?cè)诼暶饕?A 的時(shí)候?qū)?D1 排除掉泳姐,這樣也避免了包沖突效拭。
舉個(gè)??:將 zookeeper 的 jline 依賴排除
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.1</version>
<exclusions>
<exclusion>
<groupId>jline</groupId>
<artifactId>jline</artifactId>
</exclusion>
</exclusions>
</dependency>
檢測(cè)包沖突工具
mvn dependency:help
mvn dependency:analyze
mvn dependency:tree
mvn dependency:tree -Dverbose
詳細(xì)參考:
mvn dependency
mvn dependency:tree
依賴管理解決什么問(wèn)題
當(dāng)同一個(gè)工程內(nèi)有多個(gè)模塊時(shí),并且要求多個(gè)模塊使用某個(gè) jar 包的相同版本胖秒,為了方便統(tǒng)一版本號(hào)缎患,升級(jí)版本號(hào),需要提取出一個(gè)父親模塊來(lái)管理子模塊共同依賴的 jar 包版本阎肝。
舉個(gè)??:有兩個(gè)模塊 projectA, projectB挤渔,它們的依賴分別如下所示:
projectA:
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
projectB:
<project>
...
<dependencies>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
projectA 和 projectB 共同依賴了 group-a/artifact-b/1.0,提取公共依賴风题,生成 parent判导, parent 依賴如下:
<project>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
則 projectA 和 projectB 均不需要指定 group-a/artifact-b 的 version 信息,未來(lái)升級(jí) version 信息時(shí)沛硅,只需要在 parent 內(nèi)部指定眼刃。
projectA:
<project>
...
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
</dependency>
</dependencies>
</project>
projectB:
<project>
...
<dependencies>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
</dependency>
</dependencies>
</project>
依賴范圍
如果不顯示執(zhí)行 <scope> 屬性時(shí),默認(rèn) <scope>compile</scope>摇肌。
scope 有哪些屬性:compile, provided, runtime, test, system 等擂红。
詳細(xì)參考:依賴范圍
最佳實(shí)踐
(1)項(xiàng)目中源代碼使用的 jar 包一定在 pom.xml 中顯示引用。
(2)經(jīng)常 check 一下包沖突围小,檢查是否需要處理昵骤。
(3)當(dāng)使用多個(gè)模塊時(shí),parent 一定要使用包管理模塊來(lái)規(guī)范 Jar 包版本吩抓,而不是包依賴模塊直接引入依賴涉茧。 dependencyManagement vs dependencies
參考
參考
maven 入門指南
maven 生命周期
Maven 默認(rèn)插件以及功能
maven 依賴管理
maven-shade-plugin 入門指南
maven-assembly-plugin 入門指南
maven 依賴機(jī)制