覆盖 Spring Boot 依赖的版本号

1、简介

Spring Boot 为大多数常用的依赖、第三方库都定义好了最兼容的版本号(如 JPA、MySQL 驱动、Redis 客户端)。得益于此,我们可以快速地创建一个新应用。

但,有时出于特殊原因,我们需要修改这些预定义的依赖版本号。

2、Spring Boot 依赖清单(BOM)

Spring Boot 使用 Bill of Materials (BOM) 来定义依赖和版本。

大多数 Spring Boot 项目都继承自 spring-boot-starter-parent,而 spring-boot-starter-parent 本身又继承自 spring-boot-dependencies 。后者就是 Spring Boot BOM,它只是一个 Maven POM 文件,其中有一个很大的 ependencyManagement 节点:

<dependencyManagement>
    <dependencies>
        <dependency>
            ...
        </dependency>
        <dependency>
            ...
        </dependency>
    </dependencies>
</dependencyManagement>

通过使用 Maven 的 dependencyManagement,BOM 可以指定依赖的默认版本(如果应用使用了这个依赖)。

Spring Boot BOM 中的一个依赖如下:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-amqp</artifactId>
    <version>${activemq.version}</version>
</dependency>

这意味着,在项目中依赖了 ActiveMQ,就会使用这个默认的版本。

另外,注意。版本是使用属性占位符指定的。这是 Spring Boot BOM 中的常见做法,它在自己的 properties 部分中提供了该属性和其他属性的值。

3、覆盖 Spring Boot 管理的依赖版本

既然已经了解了 Spring Boot 如何管理依赖版本,那就来看看如何覆盖它们。

3.1、Maven

对于 Maven,有两种方法来覆盖 Spring Boot 管理的依赖版本。首先,对于 Spring Boot BOM 通过属性占位符指定版本的任何依赖,我们只需在项目 POM 中设置该属性即可:

<properties>
    <activemq.version>5.16.3</activemq.version>
</properties>

这将导致任何使用 ${activemq.version} 属性的依赖使用我们指定的版本,而不是 Spring Boot BOM 中的版本。

此外,如果版本是在 BOM 的 dependency 标签中明确指定的,而不是占位符,那么我们只需在项目 dependency 条目中明确覆盖 version 即可:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-amqp</artifactId>
    <version>5.16.3</version>
</dependency>

3.2、Gradle

Gradle 需要一个插件来遵循 Spring Boot BOM 的依赖管理。

包含该插件并导入 BOM:

apply plugin: "io.spring.dependency-management"
dependencyManagement {
  imports {
    mavenBom 'io.spring.platform:platform-bom:2.5.5'
  }
}

现在,如果想覆盖某个特定依赖的版本,只需将 BOM 中的相应属性指定为 Gradle ext 属性即可:

ext['activemq.version'] = '5.16.3'

如果 BOM 中没有可覆盖的属性,可以在声明依赖时直接指定版本:

compile 'org.apache.activemq:activemq-amqp:5.16.3'

3.3、注意

Spring Boot 本身就是通过 BOM 中指定的依赖进行构建和测试的。如果你指定了不同的依赖版本,可能会导致不兼容的问题发生。因此,这种情况下你必须要对应用进行测试。

没有特殊原因,不建议覆盖 Spring Boot 依赖的默认版本号!

4、查找依赖版本

了解了 Spring Boot 如何管理依赖的版本后,再来看看如何查找项目正在使用的依赖的当前版本。

4.1、Maven

Maven 提供了一个 goal,可以用它来显示所有依赖及其版本的列表。

例如,运行命令:

mvn dependency:tree

你可以看到类似如下的输出:

[INFO] com.baeldung:dependency-demo:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:2.5.7-SNAPSHOT:compile
[INFO] |  +- org.springframework.boot:spring-boot-starter:jar:2.5.7-SNAPSHOT:compile
[INFO] |  |  +- org.springframework.boot:spring-boot:jar:2.5.7-SNAPSHOT:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-autoconfigure:jar:2.5.7-SNAPSHOT:compile
[INFO] |  |  +- org.springframework.boot:spring-boot-starter-logging:jar:2.5.7-SNAPSHOT:compile
[INFO] |  |  |  +- ch.qos.logback:logback-classic:jar:1.2.6:compile
[INFO] |  |  |  |  \- ch.qos.logback:logback-core:jar:1.2.6:compile

输出结果会显示项目依赖的所有工件(artifact)和版本。这些依赖关系以树形结构显示,便于识别每个依赖是如何导入到项目中的。

在上例中,logback-classicspring-boot-starter-logging 的依赖,而 spring-boot-starter-logging 库本身又是 spring-boot-starter 模块的依赖。这样,我们就可以沿着树状结构追溯到顶层项目。

4.2、Gradle

Gradle 提供了一个生成类似依赖关系树的 task。

运行以下命令:

gradle dependencies

你可以看到类似于如下的输出:

compileClasspath - Compile classpath for source set 'main'.
\--- org.springframework.boot:spring-boot-starter-web -> 1.3.8.RELEASE
     +--- org.springframework.boot:spring-boot-starter:1.3.8.RELEASE
     |    +--- org.springframework.boot:spring-boot:1.3.8.RELEASE
     |    |    +--- org.springframework:spring-core:4.2.8.RELEASE
     |    |    \--- org.springframework:spring-context:4.2.8.RELEASE
     |    |         +--- org.springframework:spring-aop:4.2.8.RELEASE

和 Maven 的输出一样,可以很容易地识别出每个依赖被拉入项目的原因,以及正在使用的版本。

5、总结

本文介绍了 Spring Boot 如何管理依赖的版本,以及如何在 Maven 和 Gradle 中覆盖这些依赖的版本。


Ref:https://www.baeldung.com/spring-boot-override-dependency-versions