Maven 依賴管理

管理包依賴是 Maven 核心功能之一,下面通過如何引入 jar 包;如何解析 jar 包依賴;包沖突是如何產(chǎn)生;如何解決包沖突;依賴管理解決什么問題;什么是依賴范圍;使用包依賴的最佳實(shí)踐等 6 個(gè)問題來介紹。

如何引入 jar 包

在代碼開發(fā)時(shí),如果需要使用第三方 jar 包提供的類庫,那么需要在 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)系不斷傳遞,直至沒有依賴。
例如:上述 pom.xml 引入 zookeeper 依賴,實(shí)際引入的 jar 包有:


zookeeper jar 依賴項(xiàng)

包沖突如何產(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 面對 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è)依賴路徑長度都是 2,那么就選擇最先聲明。

移除依賴

如果我們不想通過 A->B->->D1 引入 D1 的話,那么我們在聲明引入 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>

檢測包沖突工具

mvn dependency:help
mvn dependency:analyze
mvn dependency:tree
mvn dependency:tree -Dverbose

詳細(xì)參考:
mvn dependency
mvn dependency:tree

依賴管理解決什么問題

當(dāng)同一個(gè)工程內(nèi)有多個(gè)模塊時(shí),并且要求多個(gè)模塊使用某個(gè) jar 包的相同版本,為了方便統(tǒng)一版本號(hào),升級(jí)版本號(hào),需要提取出一個(gè)父親模塊來管理子模塊共同依賴的 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 信息,未來升級(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 一定要使用包管理模塊來規(guī)范 Jar 包版本,而不是包依賴模塊直接引入依賴。 dependencyManagement vs dependencies

參考

參考

maven 入門指南
maven 生命周期
Maven 默認(rèn)插件以及功能
maven 依賴管理
maven-shade-plugin 入門指南
maven-assembly-plugin 入門指南
maven 依賴機(jī)制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Maven工程的拆分與聚合(重點(diǎn)) 一個(gè)完整的早期開發(fā)好的crm項(xiàng)目,現(xiàn)在要使用maven工程對它進(jìn)行拆分,這時(shí)候...
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,628評(píng)論 19 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,276評(píng)論 6 342
  • 大家所說的“正念”是什么,宗教?跟我有關(guān)系嗎? 說明“正念”是什么并不容易,本文我先講關(guān)于正念的一部分知識(shí),后期在...
    張新_心理閱讀 1,848評(píng)論 2 3
  • 木木,好久不見。今年是2016年,轉(zhuǎn)眼我們都已經(jīng)準(zhǔn)備大四了。 2009年,《海角七號(hào)》在大陸首映,那時(shí)候我還不認(rèn)識(shí)...
    晨小昕閱讀 2,120評(píng)論 1 0

友情鏈接更多精彩內(nèi)容