Maven 依賴管理

糖果朵朵發表於2020-10-19

Maven依賴管理

Maven最小依賴

pom.xml檔案最小內容:

<?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.example</groupId>
<!--專案唯一ID,一個groupId下可能有多個專案,靠artifactId來區分-->
    <artifactId>maven-demo</artifactId>
    <!-- 版本號 -->
<version>1.0-SNAPSHOT</version>
<!--打包方式(jar、war、pom),不配置預設打jar包-->
<packaging>jar</packaging>
 
</project>

Maven依賴範圍

Maven用於專案的構建,它會執行一系列編譯、測試和部署執行等操作,在不同的操作下使用的classpath不同,依賴範圍就是用來控制依賴與三種 classpath(編譯classpath、測試classpath、執行classpath)的關係;

Maven有以下幾種依賴範圍:

  • compile:編譯依賴範圍(預設),使用此依賴範圍對於編譯、測試、執行三種classpath 都有效,即在編譯、測試和執行的時候都要使用該依賴jar包;
  • test:測試依賴範圍,只能用於測試classpath,而在編譯和執行主程式專案時無法使用此jar包依賴,典型的是JUnit,它只用於編譯測試程式碼和執行測試程式碼的時候才需要;
  • provided: 此依賴範圍,對於編譯和測試classpath有效,而對執行時無效,典型的是servlet包;
  • runtime:執行時依賴範圍,對於測試和執行classpath有效,但是在編譯主程式碼時無效,典型的就是JDBC驅動實現;
  • system:系統依賴範圍,和provided依賴範圍一致,使用system範圍的依賴時必須通過systemPath元素顯示地指定依賴檔案的路徑,不依賴Maven倉庫解析,所以可能會造成建構的不可移植,謹慎使用;jar包存放在專案下或者磁碟。

在這裡插入圖片描述

Maven的依賴範圍通過scope標籤定義。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <!--依賴範圍-->
    <scope>test</scope>
</dependency>

Maven依賴傳遞

當我們在專案中加入spring-web依賴,而spring-web又依賴了spring-beans、spring-core、spring-jcl等,那麼這3個依賴也被自動加了進來,這種叫做依賴的傳遞;
而scope元素的值會對這種傳遞依賴會有影響,影響結果如下圖:
在這裡插入圖片描述
A依賴於B,B依賴於C,我們說A對於B是第一直接依賴,B對於C是第二直接依賴,而A對於C是傳遞性依賴。
上圖第一列:即A->B的scope的值
上圖第一行:即B->C的scope的值
行列交叉的值顯示的是A對於C最後產生的依賴效果。

依賴傳遞有一定規律:
(1)當B->C依賴是compile的時候(表中第2列),那麼A->C的依賴範圍和A->B的sope是一樣的;
(2)當B->C的依賴是test時(表中第3列),那麼B->C的依賴無法傳遞給A;
(3)當B->C的依賴是provided(表第4列),只傳遞A->C的scope為provided的情況,其他情況B->C的依賴無法傳遞給A;
(4)當B->C的依賴是runtime(表第5列),那麼C按照B->C的scope傳遞給A;

Maven依賴調節

依賴調節的兩個原則:
(1)路徑最近原則。
(2)最先宣告原則。

實際開發中可能存在這種情況,A->B->C->X(1.0),A->D->X(2.0),此時X出現了2個版本1.0和2.0,此時A專案會選擇X的哪個版本?
解決這種問題,maven有2個原則:

  • 路徑最近原則
    上面A->B->C->X(1.0),A->D->X(2.0),X的2.0版本距離A更近一些,所以A專案會選擇2.0;
    但如果出現了路徑距離一樣,如:A->B->X(1.0),A->D->X(2.0),此時maven又如何選擇?
  • 最先宣告原則
    如果出現了路徑一樣,此時會看A的pom.xml中所依賴的B、D在dependencies中的位置,誰的宣告在最前面,就以誰的為準,比如A->B在前面,那麼最後X會選擇1.0版本。

Maven可選依賴

比如情況如下:
A->B中scope: compile
B->C中scope: compile
按照上面的依賴傳遞性,C會傳遞給A,被A依賴;
如果此時B不想讓C被A自動依賴,怎麼辦?
dependency元素下采用optional選項配置,它是一個boolean值,表示是一個可選依賴,B->C時將這個值置為true,那麼C不會被A自動引入;
斷開依賴傳遞性

Maven依賴排除

A->B的1.0版本,B->C的1.0版本,scope都預設為compile,根據依賴傳遞性,C會傳遞給A,會被A自動依賴,但C此時有個更新的版本2.0,A想使用2.0的版本,則需要使用依賴排除;
在dependency中使用exclusion進行以來排除。

相關文章