使用Version Catalog在项目之间共享版本

309 阅读6分钟

在进行Spring Boot进行微服务开发,或者有很多个应用时,不同的项目之间可能会因为使用Spring Boot的版本不同而造成彼此时间的不兼容。这个时候就可以通过统一项目的依赖版本来避免这个问题。本文将介绍使用Gradle的Version Catalog来统一项目版本的方法。

关于Version Catalog

Version Catalog是Gradle 7.0+引入的一个新特性(在7.4版本稳定),旨在简化和几种管理项目中的依赖版本。它允许开发人员在一个单独的文件或者项目中定义依赖的版本,这样做可以:

  1. 集中管理:将依赖和版本作为单独的项目,可以单独进行版本管理,便于维护和更新。
  2. 避免版本冲突:通过统一的版本管理,减少不同模块间因为引入依赖的不同版本而冲突。

在多个项目间共享版本

将Version Catalog作为一个单独的项目可以实现版本号和项目的解耦,这个项目也可以单独进行升级。

创建Gradle项目

这一步比较简单,创建一个空项目即可。为了后文方便阅读,我们为这个项目设置一些基础信息:

  • Group Id:com.aquarius
  • Artifact Id:aquarius-dependency-management
  • 配置文件语言选择Kotlin风格,使用Groovy的读者可以参考后面的代码自行编写
  • 版本号是1.0.0

添加Version Catalog插件

打开项目的build.gradle.kts文件,添加插件:

plugins {
    `version-catalog`
}

定义版本清单

预定义版本号(可选)

如果有多个依赖有相同的版本,比如Kotlin的各种插件,那么就可以将版本号统一声明,便于后面使用,代码如下:

catalog {
    versionCatalog {
        version("kotlin", "2.0.20")  // 当然也可以把"kotlin"单独定义一个变量,方便使用
        version("spring-boot", "3.3.3")
    }
}

定义版本清单

catalog {
    versionCatalog {
        // 前面定义的版本
        plugin("kotlin-jvm", "org.jetbrains.kotlin.jvm").version("2.0.20")
        plugin("kotlin-spring", "org.jetbrains.kotlin.plugin.spring")
            .versionRef("kotlin")  // 这里引用名为"kotlin"的版本号,即"2.0.20"
        // 定义库时可以像上面一样使用version函数,或者像下面一样直接写在依赖中
        library("kotlin-logging", "io.github.oshai:kotlin-logging-jvm:7.0.0")
    }
}

依赖命名规则和类型安全的访问器

依赖命名规则

在前面定义版本清单的时候,我们声明的kotlin-jvmkotlin-springkotlin-logging等都是对应依赖的别名,可以用来在其他项目中生成安全的访问器。依赖别名是由一系列以横线“-”(推荐方法)、下划线“_”或者点“.”分隔的标识符组成。标识符可以是ASCII字符(推荐使用小写字母),后面可以添加数字。下面列举一部分标识符规则(引用自Gradle官网):

  • guava是一个合法的依赖别名
  • groovy-core是一个合法的依赖别名
  • commons-lang3是一个合法的别名
  • androidx.awesome.lib是合法的别名
  • this.#is.not!不是合法的别名

类型安全的访问器

假设其他项目在使用这个版本清单的时候定义的名称是libs,那么对于下面的别名,将会生成对应的访问器(引用自Gradle官网):

  • guava对应libs.guava
  • groovy-core对应libs.groovy.core
  • groovy-xml对应libs.groovy.xml
  • groovy-json对应libs.groovy.json
  • androidx.awesome.lib对应libs.androidx.awesome.lib 当然,如果想要避免上面的分组,可以使用大写字母来避免分割:
  • groovyCore对应libs.groovyCore
  • groovyXml对应libs.groovyXml
  • groovyJson对应libs.groovyJson

保留字和特殊命名

  1. extensionsclassconvention保留字,禁止用于定义版本清单的别名。
  2. bundlesversionsplugins不能用于访问器的第一个分组,即versions-dependency不被允许,但是versionDependency或者dependency-version是合法的别名。

将版本清单发布到代码仓库中

在前面我们已经定义了版本清单的内容,接下来将代码发布到仓库中,便于其他项目使用,这里我们打开build.gradle.kts文件,所有的操作都在这里进行:

引入插件

// 添加Maven Publish插件
plugins {
    // ...
    `maven-publish`
}

配置发布内容

publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["versionCatalog"])
        }
    }
}

重新加载Gradle项目,此时会在项目中看见一系列新的Gradle任务: ![[新增的Gradle任务.png]] 此时可以双击publishToMavenLocal发布到本地仓库,也可以使用其他的发布方法,具体使用可以参考Gradle官网的文档

对依赖进行版本管理(可选)

为了进一步管理依赖的版本,我们可以使用Gradle Release插件来对依赖进行版本管理。Gradle Release插件基于代码提交记录,支持Git、SVN、Mercurial和Bazaar。首先引入依赖:

plugins {    
    id("net.researchgate.release") version "3.0.2"  
}

重新加载Gradle项目,这时会出现相关的任务,我们点击release即可: ![[Gradle Release的任务列表.png]] 如果使用Git管理项目的话,需要将当前分支命名为main,而不是master。此时就会在命令行进行以下操作:

  1. 检查所有未提交的代码,包括添加、修改、删除以及未被管理的代码。
  2. 检查代码变动。
  3. 签出到发布分支,并合并当前分支(只有Git有,且需要配置pushReleaseVersionBranch)。
  4. 移除项目版本号的SNAPSHOT(如果有的话)。
  5. 提示用户输入当前版本号,这一步需要用户输入
  6. 检查项目使用使用SNAPSHOT版本号。
  7. 构建项目(执行build命令)。
  8. 提交项目代码(如果使用SNAPSHOT版本号)。
  9. 为当前版本添加Tag
  10. 签出到当前工作分支(条件同第三步)。
  11. 提示用户输入下个版本号(用于下一次发布时第5部的默认值),这一步需要用户输入
  12. 使用新的版本号提交项目代码。 之后就可以对Dependency Management项目进行版本管理,方便升级项目中的公共依赖。

在其他项目中使用版本清单

创建另一个项目,在settings.gradle.kts文件中声明使用的版本清单:

dependencyResolutionManagement {
    // 其实也可以在这里声明项目的全局代码仓库,但是这个API并不稳定
    versionCatalogs {  
        create("libs") {
            from("com.aquarius:aquarius-dependency-management:1.0.0")  
        }  
    }
}

这里的libs就是我们为Version Catalog起的别名,在构建项目后,会自动生成一个libs变量,我们就可以直接使用这个变量来声明依赖,无需手动指定版本。 在项目的build.gradle.kts文件中,我们可以使用libs提供的各种预定义的依赖项:

plugins {
    // 定义插件时需要使用alias定义
    alias(libs.kotlin.jvm)
    alias(libs.kotlin.spring)
}

dependencies {
    // 定义依赖时可以和不使用Version Catalog时一样
    implementation(libs.kotlin.logging)
}

注意事项

Gradle依赖的Type和Classifier

在使用某些依赖时,我们会用到它的不同的变体(Variant),比如使用Spring Data Jpa和Querydsl时,如果使用Spring Boot 3,那么需要引用classifier为jakarta的变体。这种行为无法在定义Version Catalog时进行,只能等到声明依赖的时候才能实现,详见参考链接中的GitHub Issue,下面给出合适的代码:

dependencies {
    kapt(libs.querydsl.jpa) {
        classifier = "jakarta"
        // 当然,也可以定义诸如type = "aar"等其他内容
    }
}

参考链接

这篇博客的编写主要参考Gradle官网的文档,以及一篇介绍Version Catalog的博客,其中关于Classifier的部分参考自GitHub的Issue: