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元素的使用,你弄明白了?》
相關文章
- 你的專案使用Optional了嗎?
- 終於弄明白了 RocketMQ 的儲存模型MQ模型
- Maven依賴中的scope詳解Maven
- Maven中optional標籤詳解(轉)Maven
- Maven中的dependency的scope作用域詳解Maven
- maven中的scope標籤類別詳解Maven
- vue中style下scope的使用和坑Vue
- maven中profile元素的作用意義和用法Maven
- Deno 正式釋出,徹底弄明白和 node 的區別
- 終於弄明白了 Singleton,Transient,Scoped 的作用域是如何實現的
- maven中scope依賴範圍與classpath的關係Maven
- Maven-POM中的各種scope的行為總結Maven
- 理解vue中的scope的使用Vue
- Promise 你真的用明白了麼?Promise
- 終於搞懂Spring中Scope為Request和Session的Bean了SpringSessionBean
- null 不好,我推薦你使用 OptionalNull
- null 不好,我真的推薦你使用 OptionalNull
- angular中的scopeAngular
- Maven依賴scope範圍詳解Maven
- Maven optional關鍵字透徹圖解Maven圖解
- jsp無法使用bean的問題 弄了兩天了想自殺了JSBean
- 請你說說 Vue 中 slot 和 slot-scope 的原理(2.6.11 深度解析)Vue
- CTQ難理解?這樣說你就明白了
- MySQL索引-B+樹(看完你就明白了)MySql索引
- #07你認真學了css?偽類和偽元素CSS
- Unfolder中的補丁和元素使用方法
- TypeScript 中 Optional Chaining 和 Nullish CoalescingTypeScriptAINull
- 關於python編碼,你真的明白了嗎Python
- [譯] 一張圖弄明白 Vuex 裡該存放什麼樣的資料Vue
- 控制檯獲取AngularJS某個元素的ScopeAngularJS
- 使用Maven打包你的應用——maven-jar-plugin & maven-assembly-plugin & maven-shade-pluginMavenJARPlugin
- Java Optional使用的最佳實踐Java
- Spring中的@scope註解Spring
- 關於資料庫事務的基本概念,我還弄不明白。資料庫
- YUI TreeView搞明白了UIView
- 機器學習,看完就明白了機器學習
- 使用Java8中的Optional類來消除程式碼中的null檢查JavaNull
- Java Optional使用指南Java