一个中大型的 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

Java 使用 Maven BOM 统一管理版本号的更多相关文章

  1. android studio 统一管理版本号配置

    1.在android 的根目录新建一个versions.gradle 2.在这里面声明 各个第三方库的版本,写法有两种,第一种,写ext 扩展, 引用的时候, 第二种: 然后在project级的bui ...

  2. 【Android Studio】Gradle统一管理版本号引用配置

    1.在根目录下的build.gradle文件下添加 ext{ .... } 中的内容 ...... // Define versions in a single place ext { // SDK ...

  3. Android Studio配置统一管理依赖版本号引用

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo采用的是其中一个方案,其他方案请阅读参考资料<Android Studio中统一管理版本号引用配置> 使用步骤 ...

  4. SpringBoot微服务电商项目开发实战 --- 模块版本号统一管理及Redis集成实现

    上一篇文章总结了基于SpringBoot实现分布式微服务下的统一配置.分环境部署配置.以及服务端模块的分离(每一个提供者就是一个独立的微服务).微服务落地.Dubbo整合及提供者.消费者的配置实现.本 ...

  5. Maven(十三)Maven统一声明版本号

    情景:当使用Spring下的多个包时,为了方便版本号的统一管理,避免出现因不同版本号造成的错误,必须更改为统一的版本号,但是当项目过多时手动修改不方便,因此引入此标签可以方便进行统一的修改. pom. ...

  6. Javascript中怎样获取统一管理的Java提示语

    项目开发中,各个页面.各个业务操作都会使用提示语.面对这么多message,更好的方式是统一管理这些消息. 这样在做国际化的时候进行统一处理也变的方便. 推荐方案使用数据库来管理全部提示语,在项目启动 ...

  7. maven 使用dependencyManagement统一管理依赖版本

    今日思语:人生方方长长,努力把她磨成方圆,所以 加油咯~ 使用maven可以很方便的进行项目依赖的管理,即可以管理我们显示引入具体版本的依赖,也可以管理某些第三方引入的一些依赖的版本,从而能更好的实现 ...

  8. Maven如何利用父工程对版本进行统一管理

    项目开发中我们该怎么对项目依赖的版本进行统一管理呢 答:创建一个父级工程,让所有的业务模块都继承该父级工程,即所有的业务都为Module 在父级工程pom文件添加<dependencyManag ...

  9. maven依赖排除、顺序原则、版本统一管理

    <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core& ...

随机推荐

  1. 12月17日BGV币行情分析

    目前BGV收于353.95美金,较前一交易日上涨28.25%. 非小号数据显示,BGV最大客户aofexpay.ngk出现+490.2349的持币变化,其次减仓数额均不大,分别为-80.1,-30,- ...

  2. 【原创】Linux虚拟化KVM-Qemu分析(十)之virtio驱动

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: KVM版本:5.9 ...

  3. Django Admin 实现三级联动的示例代码(省市区)===>小白级

    一  使用环境 开发系统: windows IDE: pycharm 数据库: msyql,navicat 编程语言: python3.7  (Windows x86-64 executable in ...

  4. 小白养成记——Java比较器Comparable和Comparator

    一.使用情景 1.  调用Arrays.sort()方法或Collections.sort()方法对自定义类的对象排序 以Arrays.sort()为例.假定有如下自定义的Person类 1 publ ...

  5. 聊一聊JVM

    JVM 什么是JVM? ​ JVM是java虚拟机的缩写,本质上是一个程序,能识别.class字节码文件(.java文件编译后产生的二进制代码),并且能够解析它的指令,最终调用操作系统上的函数,完成我 ...

  6. Java方法详解

    Java方法详解 什么是方法? Java方法是语句的集合,它们在一起执行一个功能. 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 示例: packag ...

  7. 内核报错kernel:NMI watchdog: BUG: soft lockup - CPU#1

    1.现象描述 系统管理员电话通知,描述为一台服务器突然无法ssh连接,登录服务器带外IP地址并进入远程控制台界面后,提示Authentication error,重启后即可正常进入系统,进入后过20分 ...

  8. redis基础:redis下载安装与配置,redis数据类型使用,redis常用指令,jedis使用,RDB和AOF持久化

    知识点梳理 课堂讲义 课程计划 1. REDIS 入 门 (了解) (操作)   2. 数据类型 (重点) (操作) (理解) 3. 常用指令   (操作)   4. Jedis (重点) (操作) ...

  9. 循环单链表定义初始化及创建(C语言)

    #include <stdio.h> #include <stdlib.h> /** * 含头节点循环单链表定义,初始化 及创建 */ #define OK 1; #defin ...

  10. FTP操作/Passive/Active控制

    1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.IO; 5 using ...