Maven学习(五)————依赖的特性辨析
引言
在Maven 中,依賴有一些特性必須我們掌握,如依賴的傳遞性。
一、依賴的傳遞性
其實依賴的傳遞性非常好理解。
上圖,如果 Maven 項目 B 已經依賴了 C?,A 又依賴了 B,那么 A 不需要再在自己的pom 中重復引入 C 的依賴聲明,就可以直接使用 C 中的代碼了。
顯而易見,依賴能夠傳遞的好處就是,不必反復聲明相同的依賴,在“最下面” 的工程中依賴一次就可以。在實際開發(fā)中,往往會有一個專門管理依賴的模塊項目。
不過這種情況不是絕對的,這里有一個非常關鍵的限制,即依賴的 Scope。
Scope 指的是“作用域”,對于依賴來說,就指的是某個依賴是否參與 compile 、test、打包等幾個重要的事件。
我們在pom 中聲明 <dependency> 的時候,可以順便聲明<scope>,默認情況下是就是 compile 。對于 scope 是 compile 的依賴,上面的依賴傳遞關系是成立的,即 A 可以不必明確聲明依賴 C 就能使用C 中的代碼。
另外,雖然依賴的傳遞性非常方便,但并不適合所有場景,有些情況下,是需要進行直接依賴的,比如,當模塊項目進行拆分重組,那么有些間接依賴可能就會被切斷傳遞的鏈路,這種情況,就需要在搭建項目之初考慮到這個問題。
二、依賴的作用域
我在網(wǎng)上看到一些對maven 依賴的 scope 屬性的講解,貌似都不太敢于稱其為“作用域”,不過我覺得“作用域”這個翻譯應該是比較合適的。
引述一下官網(wǎng)的描述:
Dependency scope is used to limit the transitivity of a dependency, and also to affect the classpath used for various build tasks.
依賴作用域用來限制一個依賴的傳遞性,同時也可以影響類路徑下多種構建任務。
2.1 compile
默認值,?scope 聲明為 compile 的依賴對項目所有類路徑都可用,即對于編譯、測試、運行三個狀態(tài)都有效。此外,這樣的依賴還可以在依賴它的項目中進行傳遞。
2.2 test
也是一個比較常用的取值,需要顯式聲明。最常見的使用 test 作為作用域的依賴就是 JUnit,它代表此依賴在正常使用時是不要求的(is not required for normal use of the application),例如:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope> </dependency>被聲明為 test 作用域的依賴,值針對test 代碼,且無法進行依賴傳遞。
2.3 provided
這個類型的 scope 和 compile 比較像。對于編譯和測試有效,但運行時無效,典型的如servlet-api,運行時這個由容器來提供。簡單的說,就是作用域為 provided 的依賴,可以參與 編譯、測試等工作,相當于 compile 作用域,但是在打包的時候不需要打入包中,即在打包階段做了 exclude 操作。此類型的依賴也是不能傳遞的。
2.4 runtime
不太常用,對測試和運行有效,但編譯無效。可以簡單理解為對 provided 的一種互補。
2.5?system?
與provided的范圍一樣,但system必須顯示的指定依賴文件,通過<systemPath>來進行指定,是與本機綁定的,所以基本很少用到。
2.6 import
這是唯一一個只能在 <dependencyManagement> 中使用的scope 類型。最常見的用法是引入 scope = import 的spring-boot-dependencies,這個依賴是連spring-boot-starter-parent都需要繼承的父工程,用于進行諸多依賴版本的管理,使用方式是:
<dependencyManagement><dependencies><dependency><!-- Import dependency management from Spring Boot --><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>1.5.2.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies> </dependencyManagement>?這些 scope 對編譯、測試、運行可用的一覽表:
| compile | Y | Y | Y |
| test | ? | Y | ? |
| provided | Y | Y | ? |
| runtime | ? | Y | Y |
| system | Y | Y | ? |
三、作用域的傳遞性問題
scope 除了限制了依賴能夠參與編譯、測試、打包(運行)等工作外,還會對依賴的傳遞性有所影響,注意區(qū)分這兩個知識點。
前面也已經提到,如果是默認的 compile 作用域,那么依賴會一直傳遞下去,不受任何影響,而 test 作用域的依賴,就無法進行依賴傳遞。
四、依賴的原則
在項目中,依賴往往遵循兩個原則:
4.1 路徑最短優(yōu)先原則
當有同種依賴不同版本的時候,依照“路徑最短者優(yōu)先原則”。即默認使用層級關系最近的傳遞依賴。
4.2 先聲明者優(yōu)先原則
當路徑距離相同時,根據(jù)“先聲明者優(yōu)先原則”來取舍。即dependency標簽在上面的優(yōu)先使用傳遞依賴。
如上圖中 ,在 A 的pom 中如果 先聲明了 C ,那么,將會優(yōu)先使用 log4j.1.2.17版本。
五、依賴的排除
當我們不希望使用某些傳遞過來的依賴時可以使用這種方式,可能由于自動傳遞過來的此依賴版本不穩(wěn)定,想替換成其他的依賴等等。
設置方式是在希望排除某個依賴的工程中配置<exclusions>標簽即可。需要填寫groupId和artifactId兩項,那么不管什么版本的依賴都會被直接排除掉。另外,可以在層級視圖中打開pom:
?
六、統(tǒng)一管理依賴版本
前面的文章中,介紹了通過父工程來管理子工程共同的一些依賴的版本號,然后在子工程中就不需要重復進行版本號的聲明。
另外在一些只作用于當前pom 的版本號控制可以使用 <properties> 標簽來聲明,不僅僅是統(tǒng)一的版本號,項目編譯、打包時的編碼也可以進行指定。
<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>?
總結
以上是生活随笔為你收集整理的Maven学习(五)————依赖的特性辨析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL————表维护相关低频操作总结
- 下一篇: Maven学习(二)————Maven核