Maven中optional和scope元素的使用弄明白了嗎
在梳理項目的過程中發(fā)現很多開發(fā)同學對 Maven 依賴文件的配置并不了解,特別是對 Maven 的 optional 元素和 scope 元素的使用也非常隨意。這就會導致發(fā)布的 jar 包或 war 包非常 “胖”、編譯速度慢,而且還很容易生產 jar 沖突等問題。本篇文章從 optional 和 scope 的使用場景入手,讓項目實現一波瘦身。
optional 元素
這里以 Spring Boot 項目中的使用為例,比如我們在項目中經常使用的熱部署組件 spring-boot-devtools,就可以使用 optional 元素來進行定義,對應 pom 文件中配置如下:
<!--devtools 熱部署--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
那么,這里的 optional 元素設置為 true 表示何意?optional 是 Maven 依賴 jar 時的一個選項,表示該依賴是可選的,項目之間依賴不傳遞。不設置 optional(默認)或者 optional 是 false,表示傳遞依賴。
文字描述可能比較抽象,下面用具體實例場景來進行更直觀的描述,這里假設有兩個項目 A 和 B,其中 A 為父項目,B 為子項目。在父項目中引入了單元測試的依賴:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
下面針對 optional 元素的不同值進行講解。
optional 元素默認值(false)
當父項目添加 junit 依賴時,并未添加 optional 選項,也就是默認的 optional 元素的值為 false。
此時,當子項目依賴父項目時,父項目 A 和子項目 B 的關系如下:
父項目并未設置 optional 元素為 true,那么便具有依賴傳遞性。此時,子項目 B 中會直接引入父項目 A 中引入的 Junit 的 jar 包。也就是說 B 項目打包時,jar/war 包中會包含 junit 的 jar 包。
optional 元素為 true
當父項目引入 junit 依賴時,設置 optional 元素為 true。那么,子項目 B 便有了更多的選擇。
如果項目 B 不需要 Junit 的 jar 包,那么在其 pom 文件中不需進行任何處理便可以。如果 B 項目也需要對應的 jar 包依賴,可以有兩種選擇:第一、A 項目中對應依賴的 optional 設置為 false 或去掉;第二、B 項目中直接引入需要的該依賴。
parent 繼承的情況
我們經常會在 parent 項目中配置統(tǒng)一的依賴版本控制,如下:
<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <optional>true</optional> </dependency> </dependencies> </dependencyManagement>
此時,如果 B 項目需要 Junit 的 jar 包,可以直接在項目中引入,這里父項目中的 optional 配置對子項目并無影響。
綜上所述,在 Maven 項目中,恰當的使用 optional 配置,可以在很大程度上減少 jar 包的大小,提升編譯和發(fā)布速度。
scope 元素
上面講完了 optional 元素的使用,再來看看 scope 的使用。
scope 元素主要用來控制依賴的使用范圍,指定當前包的依賴范圍和依賴的傳遞性,也就是哪些依賴在哪些 classpath 中可用。常見的可選值有:compile, provided, runtime, test, system 等。
compile(編譯)
默認值。compile 表示對應依賴會參與當前項目的編譯、測試、運行等,是一個比較強的依賴。打包時通常會包含該依賴,部署時會打包到 lib 目錄下。比如:spring-core 這些核心的 jar 包。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
test(測試)
scope 為 test 表示依賴項目僅參與測試環(huán)節(jié),在編譯、運行、打包時不會使用。最常見的使用就是單元測試類了:
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency>
類似單元測試這樣的依賴,如果不設置 scope 為 test,很顯然它們會被打包、發(fā)布,但其實真是環(huán)境中并無什么作用。
runntime(運行時)
runntime 僅僅適用于運行和測試環(huán)節(jié),在編譯環(huán)境下不會被使用。比如編譯時只需要 JDBC API 的 jar,而只有運行時才需要 JDBC 驅動實現。
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.20</version> <scope>runtime</scope> </dependency>
provided(已提供)
provided 適合在編譯和測試的環(huán)境,和 compile 功能相似,但 provide 僅在編譯和測試階段生效,provide 不會被打包,也不具有傳遞性。
比如:上面講到的 spring-boot-devtools、servlet-api 等,前者是因為不需要在生產中熱部署,后者是因為容器已經提供,不需要重復引入。
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <scope>provided</scope> </dependency>
system
system 范圍依賴與 provided 類似,不過依賴項不會從 maven 倉庫獲取,而需要從本地文件系統(tǒng)提供。使用時,一定要配合 systemPath 屬性。不推薦使用,盡量從 Maven 庫中引用依賴。
<dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>1.5.0</version> <scope>system</scope> <systemPath>${java.home}/../lib/tools.jar</systemPath> </dependency>
scope 依賴的傳遞性
上面講解 scope 的不同參數值,針對這些參數值,在多個項目中的依賴傳遞性如下:
其中 B 依賴 A,C 依賴 B,傳遞性的關鍵是 B 依賴 A 時所設置的 scope 值,當 B 采用不同的值時對應的依賴關系如下:當 B 通過 test 或 provided 依賴 A 時,C 不依賴 A;當 B 通過 runtime 或 compile 依賴 A 時,C 依賴 A;
小結
經過上面對 Maven 的 optional 和 scope 元素的詳細講解,想必你已經可以對項目中的配置進行排查,確保精確的使用項目與項目之間的依賴,而不是每個項目都引入大而全的依賴文件,導致項目臃腫,編譯緩慢,沖突不斷。
到此這篇關于Maven中optional和scope元素的使用弄明白了嗎的文章就介紹到這了,更多相關Maven optional scope 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Windows系統(tǒng)中Java調用cmd命令及執(zhí)行exe程序的方法
這篇文章主要介紹了Windows系統(tǒng)中Java調用cmd命令及執(zhí)行exe程序的方法,主要用到了IOException類,需要的朋友可以參考下2016-03-03