最简单的版本声明是一个表示要使用的版本的简单字符串。Gradle 支持不同的方式来声明版本字符串

  • 确切版本:例如 1.31.3.0-beta31.0-20150201.131010-1

  • Maven 风格版本范围:例如 [1.0,)[1.1, 2.0)(1.2, 1.5]

    • []符号表示包含边界;()表示排除边界。

    • 当上限或下限缺失时,该范围没有上限或下限。

    • 符号]可用于替换(表示排除下限,[可用于替换)表示排除上限。例如]1.0, 2.0[

    • 排除上限作为前缀排除。这意味着[1.0, 2.0[还将排除所有以2.0开头且小于2.0的版本。例如2.0-dev12.0-SNAPSHOT等版本不再包含在范围内。

  • 前缀版本范围:例如 1.1.3.

    • 仅完全匹配+之前部分的版本包含在内。

    • 范围+本身将包含任何版本。

  • latest-status 版本:例如 latest.integrationlatest.release

  • Maven SNAPSHOT 版本标识符:例如 1.0-SNAPSHOT1.4.9-beta1-SNAPSHOT

版本排序

版本具有隐式排序。版本排序用于

  • 确定特定版本是否包含在范围内。

  • 在执行冲突解决时确定哪个版本“最新”(注意,冲突解决使用 "基本版本")。

版本根据以下规则进行排序

  • 每个版本都拆分为其组成“部分”

    • 字符 [. - _ +] 用于分隔版本的不同“部分”。

    • 任何同时包含数字和字母的部分都拆分为每个部分的单独部分:1a1 == 1.a.1

    • 仅比较版本的各个部分。实际分隔符并不重要:1.a.1 == 1-a+1 == 1.a-1 == 1a1(注意,在冲突解决的上下文中,有 此规则的例外情况)。

  • 2 个版本的等效部分使用以下规则进行比较

    • 如果两个部分都是数字,则较高的数字值较高1.1 < 1.2

    • 如果一个部分是数字,则它被认为高于非数字部分:1.a < 1.1

    • 如果两者都是非数字,则以区分大小写的方式按字母顺序比较部分:1.A < 1.B < 1.a < 1.b

    • 具有额外数字部分的版本被认为高于没有该部分的版本(即使该部分为零):1.1 < 1.1.0

    • 具有额外非数字部分的版本被认为低于没有该部分的版本:1.1.a < 1.1

  • 某些非数字部分对于排序目的具有特殊含义

    • dev 被认为低于任何其他非数字部分:1.0-dev < 1.0-ALPHA < 1.0-alpha < 1.0-rc

    • 字符串 rcsnapshotfinalgareleasesp 被认为高于任何其他字符串部分(按此顺序排序):1.0-zeta < 1.0-rc < 1.0-snapshot < 1.0-final < 1.0-ga < 1.0-release < 1.0-sp < 1.0

    • 这些特殊值不区分大小写,与常规字符串部分相反,并且它们不依赖于它们周围使用的分隔符:1.0-RC-1 == 1.0.rc.1

简单版本声明语义

例如,当你使用简写法声明一个版本时

build.gradle.kts
dependencies {
    implementation("org.slf4j:slf4j-api:1.7.15")
}
build.gradle
dependencies {
    implementation('org.slf4j:slf4j-api:1.7.15')
}

那么该版本将被视为一个必需版本,这意味着它至少应该是1.7.15,但可以由引擎升级(乐观升级)。

然而,对于严格版本,有一个简写法,使用!!符号

build.gradle.kts
dependencies {
    // short-hand notation with !!
    implementation("org.slf4j:slf4j-api:1.7.15!!")
    // is equivalent to
    implementation("org.slf4j:slf4j-api") {
        version {
           strictly("1.7.15")
        }
    }

    // or...
    implementation("org.slf4j:slf4j-api:[1.7, 1.8[!!1.7.25")
    // is equivalent to
    implementation("org.slf4j:slf4j-api") {
        version {
           strictly("[1.7, 1.8[")
           prefer("1.7.25")
        }
    }
}
build.gradle
dependencies {
    // short-hand notation with !!
    implementation('org.slf4j:slf4j-api:1.7.15!!')
    // is equivalent to
    implementation("org.slf4j:slf4j-api") {
        version {
           strictly '1.7.15'
        }
    }

    // or...
    implementation('org.slf4j:slf4j-api:[1.7, 1.8[!!1.7.25')
    // is equivalent to
    implementation('org.slf4j:slf4j-api') {
        version {
           strictly '[1.7, 1.8['
           prefer '1.7.25'
        }
    }
}

一个严格版本不能被升级,并且会覆盖此依赖项产生的任何传递依赖项。建议对严格版本使用范围。

上面的符号[1.7, 1.8[!!1.7.25相当于

  • 严格[1.7, 1.8[

  • 首选1.7.25

这意味着引擎必须选择一个介于 1.7(包括)和 1.8(不包括)之间的版本,并且如果图中没有其他组件需要不同的版本,它应该首选1.7.25

不带版本声明依赖项

对于较大的项目,建议的做法是不带版本声明依赖项,并使用依赖项约束进行版本声明。这样做的好处是,依赖项约束允许你在一个地方管理所有依赖项的版本,包括传递依赖项。

build.gradle.kts
dependencies {
    implementation("org.springframework:spring-web")
}

dependencies {
    constraints {
        implementation("org.springframework:spring-web:5.0.2.RELEASE")
    }
}
build.gradle
dependencies {
    implementation 'org.springframework:spring-web'
}

dependencies {
    constraints {
        implementation 'org.springframework:spring-web:5.0.2.RELEASE'
    }
}