平台和版本目录都有助于管理项目中的依赖版本,但它们服务于不同的目的,并且对依赖解析产生不同的影响

版本目录

  • 目的: 版本目录集中化和标准化依赖坐标(组、名称、版本),并在构建脚本中提供类型安全的访问器,使依赖更易于管理。

  • 对依赖图的影响: 版本目录不会直接影响依赖解析。目录中定义的版本必须在 dependencies 代码块中显式引用,一旦引用,它们的行为与任何本地声明的依赖项相同。此外,目录的内容对下游消费者是透明的,这意味着消费者无法识别依赖是本地声明的还是来自目录。

libs.versions.toml
[libraries]
mylib = { group = "com.example", name = "mylib", version = "1.0.0" }

平台

  • 目的: 平台是依赖图中的一个模块,它强制或对齐依赖项(包括传递依赖项)的版本。它影响依赖解析,并确保不同模块之间的版本一致性。

  • 对依赖图的影响: 平台应用强制版本到本地声明但没有版本的依赖项。平台中的这些版本会通过依赖图传播,影响传递依赖项和下游消费者。它们是依赖图的正式组成部分,可以决定解析期间选择的版本。

build.gradle.kts
plugins {
    `java-platform`
}

dependencies {
    constraints {
        api("com.example:mylib:2.0.0")
    }
}

将目录与平台结合使用

即使版本目录为依赖项定义了版本,如果另一个组件(例如,平台或传递依赖项)建议不同的版本,Gradle 也可能在解析期间选择不同的版本(除非使用 enforcedPlatform)。

例如,版本目录可能将 mylib 定义为版本 1.0.0,但如果平台强制使用 2.0.0,Gradle 将选择版本 2.0.0

为了确保一致的版本对齐,一个好的方法是使用版本目录来定义依赖版本,同时使用平台来强制执行它们。

版本目录

gradle/libs.versions.toml
[versions]
junit-jupiter = "5.10.3"

[libraries]
guava = { module = "com.google.guava:guava"}
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
junit-jupiter-launcher = { module = "org.junit.platform:junit-platform-launcher" }

平台

platform/build.gradle.kts
plugins {
    `java-platform`
}

javaPlatform {
    allowDependencies()
}

dependencies {
    constraints {
        api("org.junit.jupiter:junit-jupiter:5.11.1") // Enforcing specific version
        api("com.google.guava:guava:[33.1.0-jre,)") // Enforcing version range
    }
}
platform/build.gradle
plugins {
    id 'java-platform'
}

javaPlatform {
    allowDependencies()
}

dependencies {
    constraints {
        api 'org.junit.jupiter:junit-jupiter:5.11.1' // Enforcing specific version
        api 'com.google.guava:guava:[33.1.0-jre,)' // Enforcing version range
    }
}

消费者

consumer/build.gradle.kts
dependencies {
    // Platform
    implementation(platform(project(":platform")))
    // Catalog
    testImplementation(libs.junit.jupiter)
    testRuntimeOnly(libs.junit.jupiter.launcher)
    implementation(libs.guava)
}
consumer/build.gradle
dependencies {
    // Platform
    implementation platform(project(":platform"))
    // Catalog
    testImplementation libs.junit.jupiter
    testRuntimeOnly libs.junit.jupiter.launcher
    implementation libs.guava
}

同时使用目录和平台的最佳实践

  1. 使用版本目录 来定义和跨项目共享依赖坐标。它们使依赖声明保持一致且更易于管理,但不保证版本对齐。

  2. 当您需要在模块之间影响或强制版本对齐时,使用平台。平台确保依赖解析到所需的版本,尤其是在大型或多模块项目中。