本文主要記錄Maven依賴管理中關于依賴傳遞和依賴范圍的知識
Maven專案示例
創建3個maven專案,分配依賴log4j 1.2.12, 1.2.13, 1.2.14版本,
<!--專案1-->
<groupId>com.leo</groupId>
<artifactId>project1</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
</dependencies>
<!--專案2-->
<groupId>com.leo</groupId>
<artifactId>project2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
</dependency>
</dependencies>
<!--專案3-->
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
此時三個專案的依賴關系如圖所示,三個專案分別依賴了不同版本的log4j,

依賴傳遞
現在我們構造這樣一種情況,project3依賴log4j和junit,project2依賴log4j和project3,maven配置如下:
<!--專案2-->
<groupId>com.leo</groupId>
<artifactId>project2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--專案3-->
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
此時project2和project3的依賴關系如圖:

此時project2的依賴關系中出現了project3以及project3所依賴的包,對于project2來說,此時不光可以使用project3,也可以使用project3所以來的junit包,
同時我們注意到,project3依賴了1.2.14版本的log4j,這與project2本身所依賴的1.2.13版本沖突了,
此時Maven會使用如下3個規則來選擇哪個包生效:
- 依賴層級淺的包會覆寫依賴層級深的包,(示例中project2的log4j
1.2.13版本的依賴層級為1,1.2.14的依賴層級為2,因此第一層的版本生效) - 同層依賴中,先宣告的包版本生效,

- 同pom.xml檔案中,后宣告的版本生效,
依賴隱藏
如果不希望別人在依賴我的包時知道我的包依賴了哪些其他的包,那么可以在參考依賴時將其標注為<optional>true</optional>,這樣別人在使用這個包時,就不會看到這個包依賴的包,
<!--專案2-->
<groupId>com.leo</groupId>
<artifactId>project2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<!--專案3-->
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<optional>true</optional>
</dependency>
</dependencies>
這樣配置后,依賴關系如下圖所示

可以看到在project2中是無法看到project3所依賴的junit包的,當然也就無法通過依賴傳遞的方式使用到junit包,
依賴屏蔽
當我們參考別人的包時,別人的包中某些依賴我們不想引入自己的專案,那我們可以使用如下方式排除間接依賴的包,
<!--專案2-->
<groupId>com.leo</groupId>
<artifactId>project2</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.13</version>
</dependency>
<dependency>
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
<!--排除不想依賴的包-->
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<!--專案3-->
<groupId>com.leo</groupId>
<artifactId>project3</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
如此配置后的依賴關系如圖:

可以看到project2中沒有引入project3所依賴的log4j,
依賴范圍
引入依賴時,可以指定依賴包的生效范圍
| scope | 主代碼 | 測驗代碼 | 打包 | 范例 |
|---|---|---|---|---|
| compile(默認) | Y | Y | Y | log4j |
| test | Y | junit | ||
| provided | Y | Y | servlet-api | |
| runtime | Y | jdbc |
- provided解釋:例如,我們本地開發時使用了servlet-api 3.0版本進行調測,但當我們要把代碼部署到服務器的tomcat中時,服務器的tomcat不支持3.0版本的servlet-api,它自帶了自己的版本,如果我們把3.0版本打包進去,由于3.0版本會先加載,就導致在服務器的tomcat中無法運行,
- runtime解釋:jdbc平時我們在使用的時候,加載driver都是通過字串的形式,在代碼中并沒有真正參考過driver的內容,因此開發時可以不用引入需要依賴的driver,只要打包時把driver打進去就行了,
依賴范圍的傳遞性
| compile | test | provided | runtime | |
|---|---|---|---|---|
| compile | compile | test | provided | runtime |
| test | ||||
| provided | ||||
| runtime | runtime | test | provided | runtime |
行表示本專案所依賴的包配置的scope,串列示依賴包的依賴包的scope,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/543716.html
標籤:Java
