Maven依賴機制


依賴傳遞

依賴相關命令

mvn dependency:list:查看當前項目所有依賴。
mvn dependency:tree:以樹的形式顯示當前項目的所有依賴,相比mvn dependency:list 列表顯示,能很清楚的看到某個依賴是通過哪條依賴路徑引入的。
mvn dependency:analyze:分析項目的依賴關系,並確定哪些依賴是:使用和聲明、使用和未聲明、未使用和聲明。

依賴的傳遞性

如有依賴關系為A->B->C,A依賴B,稱為直接依賴。A本身不依賴C,但C通過B傳遞給A,稱C為A的傳遞性依賴

通過mvn dependency:list查看A項目的依賴列表,可以看到依賴B和C:

    [INFO] --- maven-dependency-plugin:2.8:list (default-cli) @ A --- [INFO] [INFO] The following files have been resolved: [INFO] com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile [INFO] junit:junit:jar:3.8.1:test [INFO] com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile [INFO] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

依賴調解

場景1:

路徑1:A->B->C(version:1.0)
路徑2:A->D->E->C(version:2.0)
通過兩條依賴路徑可以看出,A的傳遞性依賴的C有兩個不同版本,為了避免依賴重復,最終只能選擇一個。這種情況Maven采用路徑最近者優先的原則來處理,路徑1中C到A的距離比路徑2中C到A的距離要短,於是路徑1中C(version:1.0)最終被A依賴。

mvn dependency:tree 查看依賴路徑:

    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A --- [INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT [INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:E:jar:0.0.1-SNAPSHOT:compile [INFO] \- junit:junit:jar:3.8.1:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

場景2:

路徑1:A->B->C(version:1.0)
路徑2:A->D->C(version:2.0)
路徑1和路徑2中C到A的距離是相同的,通過路徑最近者優先原則無法判斷該使用哪個依賴,此時Maven會使用第一聲明者優先原則進行選擇,第一聲明者優先原則是指在POM依賴中聲明順序最靠前的那個依賴會被選擇。在A的POM文件中B的聲明靠前,於是C(version:1.0)會被選擇。

    <!-- A的pom.xml中依賴部分--> <dependencies> <dependency> <groupId>com.nocoffee</groupId> <artifactId>B</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>com.nocoffee</groupId> <artifactId>D</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies>

mvn dependency:tree 查看依賴路徑:

    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A --- [INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT [INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile [INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile [INFO] \- junit:junit:jar:3.8.1:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

排除依賴

在場景2中,如果要使A依賴C(version:2.0) ,則可以配置排除依賴:


  <dependencies> <dependency> <groupId>com.nocoffee</groupId> <artifactId>B</artifactId> <version>0.0.1-SNAPSHOT</version> <exclusions> <!-- 排除依賴 C --> <exclusion> <groupId>com.nocoffee</groupId> <artifactId>C</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.nocoffee</groupId> <artifactId>D</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> 

mvn dependency:tree 查看依賴路徑,A不再通過B依賴C,而是通過D依賴C:

    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A --- [INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT [INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile [INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile [INFO] \- junit:junit:jar:3.8.1:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

可選依賴

可以將某個依賴配置為可選依賴,則該依賴不會參與依賴傳遞。

以場景2為例,可以在B的pom.xml里將C配置為可選依賴,使A依賴D的C(version:2.0)。

    <!-- B的pom.xml --> <dependency> <groupId>com.nocoffee</groupId> <artifactId>C</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- 設置可選依賴 --> <optional>true</optional> </dependency>

mvn dependency:tree 查看依賴路徑,A不再通過B依賴C,而是通過D依賴C:

    [INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ A --- [INFO] com.nocoffee:A:jar:0.0.1-SNAPSHOT [INFO] +- com.nocoffee:B:jar:0.0.1-SNAPSHOT:compile [INFO] +- com.nocoffee:D:jar:0.0.1-SNAPSHOT:compile [INFO] | \- com.nocoffee:C:jar:0.0.1-SNAPSHOT:compile [INFO] \- junit:junit:jar:3.8.1:test [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------

依賴范圍

Maven在編譯、測試、運行時都會使用不同的classpath,依賴范圍是用來控制依賴和三種classpath的關系。

依賴范圍介紹

  1. compile:編譯依賴范圍,默認使用該依賴范圍,在所有classpath中都可用,並且依賴項將傳播到依賴項目。
  2. provided:已提供依賴范圍,只對於編譯和測試classpath有效,運行時無效,如Servlet API,此范圍不具有傳遞性。
  3. runtime:運行時依賴范圍,只對於測試和運行classpath有效,但在編譯主代碼時無效。
  4. test:測試依賴范圍,只對於測試的classpath有效,僅適用於測試編譯和執行階段,如junit。此范圍不具有傳遞性。
  5. system:系統依賴范圍,該依賴於三種classpath的關系和provided依賴范圍完全一致。區別在於system依賴范圍必須通過systemPath元素顯示的指定依賴文件的路徑。
  6. import:導入依賴范圍,該依賴范圍不會對三種classpath產生影響,只有在部分中的pom類型依賴項才支持此范圍,它指示要替換為指定POM的部分中的有效依賴項列表的依賴項。由於它們被替換,具有導入范圍的依賴項實際上不參與限制依賴項的傳遞性。

依賴范圍對依賴傳遞的影響

每個范圍(import導入依賴范圍除外)以不同方式影響傳遞依賴性,如下表所示。以A->B->C依賴路徑為例,左邊第一列為第一直接依賴(B在A中的依賴范圍),最上面一行為第二直接依賴(C在B中的依賴范圍),交叉單元格為傳遞性依賴范圍(C在A中的依賴范圍)。

  compile provided runtime test
compile compile(*) - runtime -
provided provided - provided -
runtime runtime - runtime -
test test - test -


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM