Maven依賴版本更新踩坑

nuccch發表於2024-06-19

問題描述

專案xx基於Spring Boot框架,其<parent>配置如下:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.2</version>
    <relativePath />
</parent>

spring-boot-dependencies-2.4.2.pom中透過<dependencyManagement>配置的caffine版本為2.8.8

<properties>
    <caffeine.version>2.8.8</caffeine.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>${caffeine.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

專案yy是一個基礎的Maven模組,在其pom.xml中新增了3.1.8版本的caffeine配置。

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>

此時在xx專案中新增對yy模組的依賴,即:

<dependency>
    <groupId>x.y.z</groupId>
    <artifactId>yy</artifactId>
    <version>1.0</version>
</dependency>

至此,重新梳理下xx,yy,Spring Boot以及caffeine的依賴關係如下:

如上圖,按照對Maven傳遞依賴的理解,此時在xx專案中使用的caffeine版本應該是在yy專案中配置的3.1.8,但實際結果卻是使用的spring-boot-dependencies-2.4.2.pom中定義的2.8.8

這顯示不是我們期望的結果!

解決辦法

經過實驗發現,凡是在<parent>中透過<dependencyManagement>管理的元件版本優先順序都比向下依賴的元件版本優先順序高。
那麼當我們需要修改元件版本以覆蓋在<parent>定義的元件版本時,該怎麼實現呢?根據不同的情況有2種辦法。

版本定義覆蓋

這種解決辦法適用於:
1.專案的<parent>直接設定為透過<dependencyManagement>管理元件的模組
2.在<parent>中透過<properties>定義了元件版本

示例:
spring-boot-dependencies-2.4.2.pom中透過<dependencyManagement>配置的caffine版本為2.8.8

<properties>
    <caffeine.version>2.8.8</caffeine.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>${caffeine.version}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

xx專案的<parent>設定為spring-boot-starter-parent

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.2</version>
    <relativePath />
</parent>

<properties>
    <caffeine.version>3.1.8</caffeine.version>
</properties>

xx<properties>重新定義<caffeine.version>為新版本號,如:3.1.8,此時將會使用在xx中定義的<caffeine.version>3.1.8)覆蓋在spring-boot-dependencies-2.4.2.pom中定義的<caffeine.version>2.8.8),也就達到了更新元件版本的目的。

重新依賴元件

倘若專案的<parent>不是直接設定為透過<dependencyManagement>管理元件的模組,或者在<parent>中沒有透過<properties>定義元件版本,那麼此時就只能在專案中重新依賴元件及版本了,這樣也能達到覆蓋在<parent>中定義的元件版本的目的。
場景1:專案的<parent>不是直接設定為透過<dependencyManagement>管理元件的模組

<!-- 沒有直接將Spring Boot設定為parent -->
<parent>
    <artifactId>test-java-samples</artifactId>
    <groupId>org.chench.extra</groupId>
    <version>1.0</version>
</parent>
<!-- Spring Boot透過dependencyManagement引入 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.4.2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

場景2:在<parent>中未透過<properties>中定義了元件版本

<!-- 在parent中未定義版本property -->
<!-- 自然也就無法透過重新定義property來達到覆蓋版本的目的 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.github.ben-manes.caffeine</groupId>
            <artifactId>caffeine</artifactId>
            <version>2.8.8</version>
        </dependency>
    </dependencies>
</dependencyManagement>

xx專案中重新依賴元件,以達到版本更新的目的。

<dependency>
    <groupId>com.github.ben-manes.caffeine</groupId>
    <artifactId>caffeine</artifactId>
    <version>3.1.8</version>
</dependency>

使用該方式解決的版本更新問題,依靠的是版本優先順序的機制。

完畢!

【參考】
記錄一次Maven依賴傳遞,模組之間依賴版本不一致問題
覆蓋 Spring Boot 依賴的版本號

相關文章