Java使用Maven BOM统一管理版本号的实现

作者:Robothy 时间:2023-08-30 00:46:00 

一个中大型的 Java 项目往往包含若干 JAR 包,这些 JAR 包有着不同的版本号。如果这些 JAR 包单独发布,然后直接通过版本号引用相应的 JAR 包,不同版本的兼容性维护将变得十分麻烦。为了解决这个问题,可以让一个特殊的模块引用这些 JAR 包,将版本号定义在这个模块中,模块中的 JAR 都是兼容的,对外发布时只发布这个特殊模块。这个特殊模块就是 BOM(Bill Of Materials)。

著名的 Spring Boot 就使用了这种方式来管理版本号,这个模块就是 spring-boot-dependencies,用户在使用 Spring Boot Starter 相关依赖时引入特定版本的 spring-boot-dependencies,然后在引入其它依赖时只需要声明 group 和 name 即可,不需要再指定版本号了。当然,在 Gradle 中使用 Spring Boot 插件,或者在 Maven 中使用 spring-boot-starter-parent 作为父模块也能够达到类似的效果。

本文将介绍如何通过 Gradle 来制作一个 BOM 以及如何在 Gradle 中使用 BOM。作为 Maven 中的一个概念,也可以使用 Maven 也可以制作和使用 BOM,但本文不涉及。

1. BOM 介绍

BOM (Bill Of Material) 是 Maven 仓库中的一个概念,它本质也是一个可被引用的包,但不包含代码,只是声明了一系列其它包。例如:Maven 中央仓库中的 spring-boot-dependencies](https://repo1.maven.org/maven2/org/springframework/boot/spring-boot-dependencies/2.4.4/) 包。它只有一个 .pom 文件。

下面是 Maven 官网上的一个简单的 BOM 的 .pom 文件:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.test</groupId>
 <artifactId>bom</artifactId>
 <version>1.0.0</version>
 <packaging>pom</packaging>
 <properties>
   <project1Version>1.0.0</project1Version>
   <project2Version>1.0.0</project2Version>
 </properties>

<dependencyManagement>
   <dependencies>
     <dependency>
       <groupId>com.test</groupId>
       <artifactId>project1</artifactId>
       <version>${project1Version}</version>
     </dependency>
     <dependency>
       <groupId>com.test</groupId>
       <artifactId>project2</artifactId>
       <version>${project2Version}</version>
     </dependency>
   </dependencies>
 </dependencyManagement>

<modules>
   <module>parent</module>
 </modules>
</project>

这个文件声明了两个包(project1 和 project2)及其版本号,和一般 .pom 文件中的声明不同的是, 节点外面还包含了一层 节点。以上就是 BOM 包中最核心的文件的基本结构了;基于 Gradle 发布 BOM 包的本质就是生成这样的一个文件。

2. 使用 Gradle 制作一个 BOM

这里我们假定要创建一个 BOM,用来统一管理三方 Java 包,其它业务模块通过引用这个 BOM 来间接引用需要使用的第三方 Java 包。工程完整代码:https://github.com/Robothy/gradle-bom-example

2.1 创建 BOM 工程

Gradle 中的 BOM 工程需要使用 java-platform 插件,这样的工程是一个不包含源代码,只包含包声明的特殊的组件,也被称为平台(platform)。

build.gradle 部分代码


plugins {
   id 'java-platform'
}

dependencies {
   constraints {
       // 声明一些三方包及其版本号
       api "org.apache.kafka:kafka-clients:2.6.0"
       api "redis.clients:jedis:3.5.2"
   }
}

上面代码中,三方包的声明没有放在 dependencies 中,而是放在了 constraints 里面。这表示如果使用了其中的包,优先使用 constraints 中声明的版本。

BOM 项目中声明包的方式有两种:

  • api 表示包在编译期可见。

  • runtime 表示包在运行期间可见。

2.2 BOM 的发布

BOM 的发布需要使用 maven-publish 插件,其发布配置如下:


publishing {
   publications {
       thirdPartPlatform(MavenPublication){
           from components.javaPlatform
           artifactId = "third-part-dependencies"
       }
   }

repositories {
       mavenLocal()
   }
}

BOM 的命名一般以 -dependencies 结尾,这里我们取名为 third-part-dependnecies。

执行 ./gradlew.bat publish 就可以将 BOM 发布到本地的 Maven 仓库了。发布的 artifacts 包含两个主要文件(.pom 和 .module)和若干校验文件。其中 .pom 的文件内容为 Maven 官方定义的 BOM 的标准格式,而.module 文件内容是 Gradle 描述元数据的一种格式。

2.3 BOM 的使用

普通的 Java 应用或者 Java 库使用 BOM 的时候需要先添加 BOM 依赖,然后使用其它的库。例如:


// 引入 BOM
implementation platform("org.example:third-part-dependencies:1.0")

// 引入包,这时不需要再指定版本号
implementation "org.apache.kafka:kafka-clients"

当然,BOM 工程或者说 platform 工程也可以使用 BOM。

使用的时候需要在 dependencies 下面引入 BOM,然后在 constraints 下面声明要使用的库,声明的时候无须指定版本。另外,需要在 configurations 中调用 javaPlatform.allowDependencies(),否则会报错。


configurations{
   javaPlatform.allowDependencies()
}

dependencies {
   api platform("org.springframework.boot:spring-boot-dependencies:2.4.4")
   constraints {
       api "org.apache.kafka:kafka-clients:2.6.0"
       api "redis.clients:jedis:3.5.2"
       api "org.springframework.batch:spring-batch-core"
   }
}

3 参考

[1] Introduction to the Dependency Mechanism

[2] The Java Platform Plugin

来源:https://www.cnblogs.com/robothy/p/14566474.html

标签:Maven,BOM,统一管理版本号
0
投稿

猜你喜欢

  • Java定时调用.ktr文件的示例代码(解决方案)

    2021-12-29 13:21:49
  • SpringBoot切面拦截@PathVariable参数及抛出异常的全局处理方式

    2023-05-27 13:59:52
  • SpringCloud实现Redis在各个微服务的Session共享问题

    2022-07-14 06:33:19
  • android判断一个Activity是否处于栈顶的实例

    2021-06-24 18:37:39
  • Mybatis联合查询的实现方法

    2021-11-27 23:26:44
  • Springboot与vue实现数据导出方法具体介绍

    2023-11-06 21:00:34
  • java自旋锁和JVM对锁的优化详解

    2022-03-02 07:05:33
  • Java中Collection、List、Set、Map之间的关系总结

    2022-11-18 21:41:42
  • Springboot整合MongoDB进行CRUD操作的两种方式(实例代码详解)

    2021-12-16 18:29:04
  • c# 开发语音识别程序

    2022-03-23 04:55:57
  • Flowable执行完毕的流程查找方法

    2023-01-30 08:53:36
  • Java 中的垃圾回收机制详解

    2023-01-11 19:32:34
  • c#图像截取实例

    2022-02-21 07:49:58
  • C#实现保存文件时重名自动生成新文件的方法

    2022-07-02 15:01:57
  • 浅谈一下单体架构的缺点是什么

    2022-07-16 06:20:12
  • 从此不再惧怕URI编码 JavaScript及C# URI编码详解

    2022-11-03 00:17:46
  • SpringCloud @RefreshScope注解源码层面深入分析

    2023-06-14 03:17:27
  • 详解Java如何创建Annotation

    2023-05-05 22:40:41
  • java eclipse 中文件的上传和下载示例解析

    2021-11-18 06:55:58
  • Android使用SQLite数据库的简单实例

    2022-03-04 13:52:50
  • asp之家 软件编程 m.aspxhome.com