Maven中optional和scope元素的使用,你弄明白了?
在梳理專案的過程中發現很多開發同學對Maven依賴檔案的配置並不瞭解,特別是對Maven的optional元素和scope元素的使用也非常隨意。這就會導致釋出的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專案中配置統一的依賴版本控制,如下:
<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包的大小,提升編譯和釋出速度。
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表示依賴專案僅參與測試環節,在編譯、執行、打包時不會使用。最常見的使用就是單元測試類了:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
類似單元測試這樣的依賴,如果不設定scope為test,很顯然它們會被打包、釋出,但其實真是環境中並無什麼作用。
runntime(執行時)
runntime僅僅適用於執行和測試環節,在編譯環境下不會被使用。比如編譯時只需要JDBC API的jar,而只有執行時才需要JDBC驅動實現。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
<scope>runtime</scope>
</dependency>
provided(已提供)
provided適合在編譯和測試的環境,和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倉庫獲取,而需要從本地檔案系統提供。使用時,一定要配合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中Scope的作用Maven
- 你的專案使用Optional了嗎?
- 終於弄明白了 RocketMQ 的儲存模型MQ模型
- Maven依賴中的scope詳解Maven
- 弄明白CMS和G1,就靠這一篇了
- Maven中的dependency的scope作用域詳解Maven
- maven中的scope標籤類別詳解Maven
- vue中style下scope的使用和坑Vue
- maven中profile元素的作用意義和用法Maven
- Maven中optional標籤詳解(轉)Maven
- Deno 正式釋出,徹底弄明白和 node 的區別
- maven中scope標籤以及exclusions 記錄Maven
- 終於弄明白了 Singleton,Transient,Scoped 的作用域是如何實現的
- Maven-POM中的各種scope的行為總結Maven
- 終於搞懂Spring中Scope為Request和Session的Bean了SpringSessionBean
- Promise 你真的用明白了麼?Promise
- null 不好,我推薦你使用 OptionalNull
- Maven依賴scope範圍詳解Maven
- 請你說說 Vue 中 slot 和 slot-scope 的原理(2.6.11 深度解析)Vue
- null 不好,我真的推薦你使用 OptionalNull
- TypeScript 中 Optional Chaining 和 Nullish CoalescingTypeScriptAINull
- Maven optional關鍵字透徹圖解Maven圖解
- Unfolder中的補丁和元素使用方法
- Optional的使用與解析
- #07你認真學了css?偽類和偽元素CSS
- MySQL索引-B+樹(看完你就明白了)MySql索引
- CTQ難理解?這樣說你就明白了
- 使用Maven打包你的應用——maven-jar-plugin & maven-assembly-plugin & maven-shade-pluginMavenJARPlugin
- alter system set ... scope=... 中的scope的含義是什麼?
- [譯] 一張圖弄明白 Vuex 裡該存放什麼樣的資料Vue
- Java Optional使用的最佳實踐Java
- 使用Optional擺脫NPE的折磨
- @Scope 註解失效了?咋回事
- vue混入mixin的使用,保證你看的明明白白!Vue
- Java Optional使用指南Java
- 更快的Maven來了Maven
- keycloak~scope客戶端模板的使用客戶端
- 使用Java8中的Optional類來消除程式碼中的null檢查JavaNull