本文主要記錄Maven依賴管理中關於依賴傳遞和依賴範圍的知識 Maven項目示例 創建3個maven項目,分配依賴log4j 1.2.12, 1.2.13, 1.2.14版本。 <!--項目1--> <groupId>com.leo</groupId> <artifactId>project1</a ...
本文主要記錄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。