前提
這篇文章是《SpringBoot2.x入門》專輯的第1篇文章,使用的SpringBoot
版本為2.3.1.RELEASE
,JDK
版本為1.8
。
主要梳理一下SpringBoot2.x
的依賴關係和依賴的版本管理,依賴版本管理是開發和管理一個SpringBoot
專案的前提。
SpringBoot
其實是通過starter
的形式,對spring-framework
進行裝箱,消除了(但是相容和保留)原來的XML
配置,目的是更加便捷地整合其他框架,打造一個完整高效的開發生態。
SpringBoot依賴關係
因為個人不太喜歡Gradle
,所以下文都以Maven
舉例。
和SpringCloud
的版本(SpringCloud
的正式版是用倫敦地鐵站或者說倫敦某地名的英文名稱作為版本號,例如比較常用的F
版本Finchley
就是位於倫敦北部芬奇利)管理不同,SpringBoot
的依賴元件釋出版本格式是:X.Y.Z.RELEASE
。因為SpringBoot
元件一般會裝箱為starter
,所以元件的依賴GAV
一般為:org.springframework.boot:spring-boot-starter-${元件名}:X.Y.Z.RELEASE
,其中X
是主版本,不同的主版本意味著可以放棄相容性,也就是SpringBoot1.x
和SpringBoot2.x
並不保證相容性,而元件名一般是代表一類中介軟體或者一類功能,如data-redis
(spring-boot-starter-data-redis
,提供Redis
訪問功能)、jdbc
(spring-boot-starter-jdbc
,提供基於JDBC
驅動訪問資料庫功能)等等。以SpringBoot
當前最新的釋出版本2.3.1.RELEASE
的org.springframework.boot:spring-boot-starter:jar:2.3.1.RELEASE
為例,用mvn dependency:tree
分析它的依賴關係如下:
這個依賴樹也印證了starter
是基於Spring
專案裝箱和擴充套件的。
SpringBoot依賴管理
如果使用Spring Initializr建立一個SpringBoot
專案的話,那麼會發現專案的POM
檔案中會加入了一個parent
元素:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
其實spring-boot-starter-parent
相當於作為了當前專案的父模組,在父模組裡面管理了當前指定的SpringBoot
版本2.3.1.RELEASE
所有依賴的第三方庫的統一版本管理,通過spring-boot-starter-parent
上溯到最頂層的專案,會找到一個properties
元素,裡面統一管理Spring
框架和所有依賴到的第三方元件的統一版本號,這樣就能確保對於一個確定的SpringBoot
版本,它引入的其他starter
不再需要指定版本,同時所有的第三方依賴的版本也是固定的。如專案的POM
檔案如下:
<!-- 暫時省略其他的配置屬性 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
這樣只需要修改parent
元素中的版本號,就能全域性更變所有starter
的版本號。這種做法其實本質上是把當前專案作為spring-boot-starter-parent
的子專案,其實在一定程度上並不靈活。這裡推薦使用另一種方式:通過dependencyManagement
元素全域性管理SpringBoot
版本,適用於單模組或者多模組的Maven
專案。專案的(父)POM
檔案如下:
<!-- spring-boot-guide 父POM -->
<properties>
<spring.boot.version>2.3.1.RELEASE</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
然後需要用到其他starter
的時候,只需要在dependencies
直接引入即可,不再需要指定版本號,版本號由dependencyManagement
中定義的版本號統一管理。
<!-- spring-boot-guide/ch0-dependency 子POM -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
SpringBoot依賴覆蓋
有些特殊的情況,可能專案中大部分的starter
使用的是相對低的版本,但是由於部分新的功能需要使用到更高版本的個別starter
,則需要強制引入該高版本的starter
。這裡舉一個例子,專案用到的SpringBoot
元件的版本是2.1.5.RELEASE
,使用的中介軟體服務Elasticsearch
的版本是7.x
,而spring-boot-starter-data-elasticsearch
支援的版本如下:
理論上可以一下子升級SpringBoot
到2.3.1.RELEASE
,其實也可以直接指定spring-boot-starter-data-elasticsearch
的版本覆蓋掉全域性的SpringBoot
元件版本,這裡應用了Maven
的依賴調解原則:
<!-- 父POM或者全域性POM -->
<properties>
<spring.boot.version>2.1.5.RELEASE</spring.boot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.3.1.RELEASE</version>
</dependency>
</dependencies>
這樣就能單獨提升spring-boot-starter-data-elasticsearch
的版本為2.3.1.RELEASE
,其他元件的版本依然保持為2.1.5.RELEASE
。
小結
目前有兩種常用的方式管理SpringBoot
元件的版本(兩種方式二選一):
- 配置
parent
元素,通過專案繼承的方式指定SpringBoot
元件的版本號,這是Spring Initializr
生成的專案中預設的配置方式。 - 配置
dependencyManagement
元素(推薦此方式),通過(父)POM
檔案統一指定SpringBoot
元件的版本號。
另外,SpringBoot
的1.x
和2.x
之間有相容性問題(最明顯的一點是2.x
中刪除了1.x
中大量的內建類,如果用到了這些SpringBoot
中的內建類,容易出現ClassNotFoundException
),降級或者升級都有比較大的風險。一般情況下,建議使用同一個大版本進行專案開發,如果確定需要進行大版本切換,請務必做完畢的功能測試。
(本文完 c-1-d e-a-20200628)
技術公眾號(《Throwable文摘》,id:throwable-doge),不定期推送筆者原創技術文章(絕不抄襲或者轉載):