1. 依賴傳遞
在Maven中,依賴是會(huì)傳遞的,假如在業(yè)務(wù)項(xiàng)目中引入了spring-boot-starter-web
依賴:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.4</version>
</dependency>
那么業(yè)務(wù)項(xiàng)目不僅直接引入了spring-boot-starter-web
依賴,還間接引入了spring-boot-starter-web
的依賴項(xiàng):
spring-boot-starter
、spring-boot-starter-json
、spring-boot-starter-tomcat
、spring-web
、spring-webmvc
。
Maven依賴關(guān)系如下圖所示:
外部庫(kù)如下圖所示:
其中,業(yè)務(wù)項(xiàng)目對(duì)spring-boot-starter-web
的依賴稱為直接依賴,對(duì)spring-boot-starter-web
的依賴項(xiàng):
spring-boot-starter
、spring-boot-starter-json
、spring-boot-starter-tomcat
、spring-web
、spring-webmvc
的依賴稱為間接依賴。
2. 依賴管理
dependencyManagement元素主要用來(lái)統(tǒng)一管理依賴項(xiàng)的版本號(hào)。
假如父項(xiàng)目的pom文件中聲明了如下依賴:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
</dependencies>
</dependencyManagement>
那么子項(xiàng)目在添加該依賴時(shí),可以不指定版本號(hào):
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
</dependency>
</dependencies>
Maven會(huì)自動(dòng)找到父項(xiàng)目中聲明的該依賴項(xiàng)的版本號(hào),如下圖所示:
這樣的優(yōu)點(diǎn)是可以統(tǒng)一在父項(xiàng)目中管理依賴項(xiàng)的版本號(hào),如果需要升級(jí)版本,只需改動(dòng)父項(xiàng)目一個(gè)地方即可,子項(xiàng)目不用改動(dòng)。
說(shuō)明:
1)dependencyManagement只是聲明依賴項(xiàng),并沒(méi)引入依賴項(xiàng),子項(xiàng)目仍需顯式引入,不過(guò)可以不指定版本號(hào)
2)如果子項(xiàng)目不想使用繼承的父項(xiàng)目中的版本號(hào),在子項(xiàng)目中指定版本號(hào)即可
3. 依賴作用域
在Maven中,可以使用scope
來(lái)指定當(dāng)前依賴項(xiàng)的作用域,常見(jiàn)的值有:compile、provided、runtime、test、import等,如下所示:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
3.1 compile
compile是默認(rèn)的作用域,如果引入依賴時(shí),沒(méi)有明確指定作用域,則依賴作用域?yàn)閏ompile。
作用域?yàn)閏ompile的依賴,在編譯、測(cè)試和運(yùn)行時(shí)都是可用的,并且會(huì)參與項(xiàng)目的打包過(guò)程,該依賴會(huì)傳遞給依賴該模塊的其他模塊。
3.2 provided
作用域?yàn)閜rovided的依賴,在編譯和測(cè)試時(shí)是可用的,在運(yùn)行時(shí)是不可用的,不會(huì)參與項(xiàng)目的打包過(guò)程,也不會(huì)傳遞給其他模塊。
比如lombok依賴會(huì)在編譯時(shí)生成相應(yīng)的get、set等方法,在運(yùn)行時(shí)就不需要這個(gè)依賴了,因此常常被指定為provided:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.16</version>
<scope>provided</scope>
</dependency>
因?yàn)楸恢付閜rovided,項(xiàng)目打包時(shí)是不包含lombok依賴項(xiàng)的,如下圖所示:
如果將上面的代碼<scope>provided</scope>
刪除的話,運(yùn)行時(shí)是下圖這樣的:
以上驗(yàn)證需將項(xiàng)目打包方式改為war,打包后查看WEB-INF/lib目錄
3.3 runtime
作用域?yàn)閞untime的依賴,在測(cè)試和運(yùn)行時(shí)是可用的,在編譯時(shí)是不可用的,會(huì)參與項(xiàng)目的打包過(guò)程,也會(huì)傳遞給依賴該模塊的
其他模塊。
說(shuō)明:
作用域?yàn)閞untime的依賴中的類,在項(xiàng)目代碼里不能直接用,用了無(wú)法通過(guò)編譯(這里指的是在src/main/java下使用)。
以mysql-connector-java為例,假如引入依賴時(shí)是下面這樣的:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
下面的示例代碼是可以編譯通過(guò)的:
如果將作用域修改為runtime,上面的示例代碼無(wú)法通過(guò)編譯:
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<scope>runtime</scope>
</dependency>
3.4 test
作用域?yàn)閠est的依賴,只在測(cè)試時(shí)可用(包括測(cè)試代碼的編譯、執(zhí)行),不會(huì)參與項(xiàng)目的打包過(guò)程,也不會(huì)傳遞給其他模塊。
常見(jiàn)的有junit、mockito等:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
因?yàn)楸恢付閠est,項(xiàng)目打包時(shí)是不包含junit依賴項(xiàng)的,如下圖所示:
如果將上面的代碼<scope>test</scope>
刪除的話,運(yùn)行時(shí)是下圖這樣的:
以上驗(yàn)證需將項(xiàng)目打包方式改為war,打包后查看WEB-INF/lib目錄
說(shuō)明:
作用域?yàn)閠est的依賴中的類或者注解只能在src/test/java下才可以使用,在src/main/java下無(wú)法使用,如junit包下的@Test
注解和org.junit.Assert
斷言類。
3.5 import
每個(gè)項(xiàng)目,一般都會(huì)繼承自一個(gè)父項(xiàng)目,在實(shí)際的工作中,這個(gè)父項(xiàng)目一般都是公司架構(gòu)組提供的帶有公司特色的一個(gè)基礎(chǔ)項(xiàng)目,
當(dāng)然也可以是spring boot官方的項(xiàng)目。
以spring boot官方的項(xiàng)目為例:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.4</version>
</parent>
這個(gè)父項(xiàng)目中,會(huì)使用dependencyManagement
標(biāo)簽對(duì)依賴項(xiàng)的版本統(tǒng)一管理,子項(xiàng)目中,可以按需引入父項(xiàng)目
dependencyManagement
中定義的依賴,但可以不指定版本號(hào)(版本號(hào)會(huì)自動(dòng)繼承父項(xiàng)目中定義的版本號(hào))。
但是存在以下2個(gè)問(wèn)題:
- Maven是單繼承的,一個(gè)項(xiàng)目只能有一個(gè)parent項(xiàng)目
- parent項(xiàng)目dependencyManagement中的依賴項(xiàng)會(huì)越來(lái)越多,不好管理
依賴作用域import的出現(xiàn)就是為了解決以上問(wèn)題,它可以通過(guò)非繼承的方式批量引入另一個(gè)依賴項(xiàng)中
dependencyManagement元素中定義的依賴項(xiàng),如下所示:
<dependencyManagement>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-bom</artifactId>
<version>${spring-session-bom.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
說(shuō)明:<scope>import</scope>
只能用在dependencyManagement下type為pom的dependency中。
以上代碼等價(jià)于添加了以下6個(gè)依賴項(xiàng):
可以看出,使用<scope>import</scope>
可以模塊化的管理依賴項(xiàng),提高復(fù)用性,pom文件也更加簡(jiǎn)潔。
3.6 區(qū)別
綜上所述,各個(gè)依賴作用域的區(qū)別如下表所示:
scope取值 | 編譯時(shí)可用 | 測(cè)試時(shí)可用 | 運(yùn)行時(shí)可用 | 是否參與打包 | 依賴傳遞 |
---|---|---|---|---|---|
compile | √ | √ | √ | √ | √ |
provided | √ | √ | × | × | × |
runtime | × | √ | √ | √ | √ |
test | × | √ | × | × | × |
4. 影響依賴傳遞的因素
4.1 依賴作用域(scope)
依賴作用域會(huì)影響依賴傳遞,從上表可以看出,如果scope為provided或者test,該依賴不會(huì)傳遞,只有scope為compile或者runtime,
該依賴才會(huì)傳遞。
4.2 可選依賴(optional)
通過(guò)dependency標(biāo)簽引入依賴時(shí),可以通過(guò)<optional>
指定該依賴是不是可選的,默認(rèn)值為false:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-711684.html
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.2.3</version>
<optional>true</optional>
</dependency>
如果<optional>
值為true,那么這個(gè)依賴不會(huì)傳遞。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-711684.html
到了這里,關(guān)于聊聊Maven的依賴傳遞、依賴管理、依賴作用域的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!