您可以指定具有精确版本或版本范围的依赖项,以定义您的项目可以使用哪些版本
dependencies {
implementation("org.springframework:spring-core:5.3.8")
implementation("org.springframework:spring-core:5.3.+")
implementation("org.springframework:spring-core:latest.release")
implementation("org.springframework:spring-core:[5.2.0, 5.3.8]")
implementation("org.springframework:spring-core:[5.2.0,)")
}
理解版本声明
Gradle 支持多种声明版本和范围的方式
版本 | 示例 | 注意 |
---|---|---|
精确版本 |
|
一个特定版本。 |
Maven 风格范围 |
|
当上限或下限缺失时,该范围没有上限或下限。 一个上限排除项作为前缀排除项。 |
前缀版本范围 |
|
仅包含与 声明版本为 |
|
|
匹配具有指定状态的最高版本。请参阅 ComponentMetadata.getStatus()。 |
Maven |
|
表示一个快照版本。 |
Maven 风格范围
有多种选项可以在 Maven 风格中指示边界
-
[
和]
表示包含边界 →[1.1, 2.0]
-
(
和)
表示排除边界 →(1.1, 2.0)
或(1.2, 1.5]
或[1.1, 2.0)
-
]
可以代替(
用于排除下限 →]1.2, 1.5]
而不是(1.2, 1.5]
-
[
可以代替)
用于排除上限 →[1.1, 2.0[
而不是[1.1, 2.0)
理解版本排序
dependencies {
implementation("org.springframework:spring-core:1.1") // This is a newer version than 1.a
implementation("org.springframework:spring-core:1.a") // This is a older version than 1.1
}
版本排序用于
-
确定特定版本是否包含在范围内。
-
在执行冲突解决时(使用“基本版本”)确定哪个版本是最新版本。
版本根据以下规则排序
-
将版本拆分为部分
-
版本使用字符
[. - _ +]
分割成部分。 -
包含数字和字母的部分会进一步拆分,例如
1a1
变成1.a.1
。 -
只比较部分,不比较分隔符,因此
1.a.1
,1-a+1
,1.a-1
, 和1a1
是等效的。(注意:在冲突解决期间有例外)。
-
-
比较等效部分
-
数字 vs. 数字: 较高的数字值被认为较高:
1.1 < 1.2
。 -
数字 vs. 非数字: 数字部分高于非数字部分:
1.a < 1.1
。 -
非数字 vs. 非数字: 部分按字母顺序和区分大小写进行比较:
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
。 -
rc
、snapshot
、final
、ga
、release
和sp
高于任何其他字符串部分,顺序如下:1.0-zeta < 1.0-rc < 1.0-snapshot < 1.0-final < 1.0-ga < 1.0-release < 1.0-sp
。 -
这些特殊值不区分大小写,它们的排序不依赖于使用的分隔符:
1.0-RC-1
==1.0.rc.1
。
-
声明富版本
当您使用简写表示法声明版本时,该版本被视为所需版本
dependencies {
implementation("org.slf4j:slf4j-api:1.7.15")
}
dependencies {
implementation('org.slf4j:slf4j-api:1.7.15')
}
这意味着最低版本将是 1.7.15
,并且引擎可以乐观地升级它。
要强制使用严格版本并确保只使用指定版本的依赖项,即使其他版本通常兼容也会被拒绝
dependencies {
implementation("org.slf4j:slf4j-api") {
version {
strictly("[1.7, 1.8[")
prefer("1.7.25")
}
}
}
dependencies {
implementation('org.slf4j:slf4j-api') {
version {
strictly '[1.7, 1.8['
prefer '1.7.25'
}
}
}
Gradle 支持一种富版本声明模型,允许您组合不同级别的版本特异性。
关键术语,从强到弱排序,是
strictly
或!!
-
这是最强的版本声明。任何不匹配此表示法的版本都将被排除。如果用于声明的依赖项,
strictly
可以降级版本。对于传递性依赖项,如果没有找到可接受的版本,依赖项解析将失败。支持动态版本。
定义后,它将覆盖任何先前的
require
声明,并清除该依赖项上已声明的任何先前的reject
。
require
-
这确保所选版本不能低于
require
所接受的版本,但可以通过冲突解决而更高,即使更高版本具有独占上限。这是直接依赖项的默认行为。支持动态版本。
定义后,它将覆盖任何先前的
strictly
声明,并清除该依赖项上已声明的任何先前的reject
。
prefer
-
这是最宽松的版本声明。它仅在没有指定更强的非动态版本时适用。
此术语不支持动态版本,并且可以补充
strictly
或require
。定义后,它将覆盖任何先前的
prefer
声明,并清除该依赖项上已声明的任何先前的reject
。
此外,还有一个不在层次结构中的术语
reject
-
此术语指定模块不接受的版本,如果选择了被拒绝的版本,将导致依赖项解析失败。
支持动态版本。
富版本声明通过依赖项或约束声明上的 version
DSL 方法访问,这使您能够访问 MutableVersionConstraint
dependencies {
implementation("org.slf4j:slf4j-api") {
version {
strictly("[1.7, 1.8[")
prefer("1.7.25")
}
}
constraints {
add("implementation", "org.springframework:spring-core") {
version {
require("4.2.9.RELEASE")
reject("4.3.16.RELEASE")
}
}
}
}
dependencies {
implementation('org.slf4j:slf4j-api') {
version {
strictly '[1.7, 1.8['
prefer '1.7.25'
}
}
constraints {
implementation('org.springframework:spring-core') {
version {
require '4.2.9.RELEASE'
reject '4.3.16.RELEASE'
}
}
}
}
要强制使用严格版本,您也可以使用 !!
表示法
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")
}
}
}
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
。
严格版本无法升级并会覆盖任何传递依赖版本,因此建议将范围与严格版本一起使用。 |
下表说明了几个用例
此依赖项的哪些版本是可接受的? | 严格 |
require |
prefer |
拒绝 |
选择结果 |
---|---|---|---|---|---|
用版本 |
1.5 |
从 |
|||
用 |
[1.0, 2.0[ |
1.5 |
介于 |
||
用 |
[1.0, 2.0[ |
1.5 |
介于 |
||
同上,已知 |
[1.0, 2.0[ |
1.5 |
1.4 |
介于 |
|
无意见,与 |
1.5 |
如果无其他意见,则为 |
|||
无意见,偏好最新发布版本。 |
|
构建时最新发布版本。 |
|||
处于边缘,最新发布,不降级。 |
|
构建时最新发布版本。 |
|||
除了 1.5 之外没有其他版本。 |
1.5 |
1.5,如果另一个 |
|||
|
[1.5,1.6[ |
最新的 |
在库中使用 strictly
需要仔细考虑,因为它会影响下游消费者。然而,如果使用得当,它有助于消费者理解哪些库组合在他们的上下文中可能不兼容。有关更多详细信息,请参阅覆盖依赖版本部分。
富版本信息保留在 Gradle 模块元数据格式中。但是,将此信息转换为 Ivy 或 Maven 元数据格式会丢失信息。将发布最高级别的版本声明—— |
支持严格版本
Gradle 通过选择依赖图中发现的最大版本来解决任何依赖版本冲突。有些项目可能需要偏离默认行为,强制使用较早版本的依赖项,例如,如果项目的源代码依赖于依赖项的较旧 API,而不是某些外部库。
通常,强制依赖是为了降级依赖。降级有常见的用例
-
在最新版本中发现了错误。
-
您的代码依赖于与新版本不二进制兼容的旧版本。
-
您的代码不使用需要较新版本的库部分。
强制依赖的版本需要仔细考虑,因为更改传递依赖的版本可能会导致运行时错误,如果外部库需要不同版本。如果可能,通常最好将源代码升级到与新版本兼容。 |
假设一个项目使用 HttpClient
库执行 HTTP 调用。HttpClient
作为传递依赖引入了 Commons Codec
版本 1.10
。然而,项目的生产源代码需要 Commons Codec
1.9
的 API,而该 API 在 1.10
中已不再可用。可以通过在构建脚本中将其声明为 strict
来强制依赖版本
dependencies {
implementation("org.apache.httpcomponents:httpclient:4.5.4")
implementation("commons-codec:commons-codec") {
version {
strictly("1.9")
}
}
}
dependencies {
implementation 'org.apache.httpcomponents:httpclient:4.5.4'
implementation('commons-codec:commons-codec') {
version {
strictly '1.9'
}
}
}
使用严格版本的后果
使用严格版本必须仔细考虑
-
对于库作者:严格版本实际上充当强制版本。它们优先于传递依赖项并覆盖传递发现的任何其他严格版本。如果消费者项目需要不同的版本,这可能导致构建失败。
-
对于消费者:严格版本在解析过程中被全局考虑。如果严格版本与消费者的版本要求冲突,它将触发解析错误。
例如,如果项目 B
严格
依赖于 C:1.0
,但消费者项目 A 需要 C:1.1
,则会发生解析错误。
为避免这种情况,建议使用版本范围和这些范围内的首选版本。
例如,B
可能不再说 strictly 1.0
,而是严格依赖于 [1.0, 2.0[
范围,但偏好 1.0
。这样,如果消费者选择 1.1
(或范围内的任何其他版本),构建将不再失败。
不带版本声明
对于大型项目,建议不带版本声明依赖项并使用平台管理版本
dependencies {
implementation("org.springframework:spring-web")
}
dependencies {
constraints {
implementation("org.springframework:spring-web:5.0.2.RELEASE")
}
}
dependencies {
implementation 'org.springframework:spring-web'
}
dependencies {
constraints {
implementation 'org.springframework:spring-web:5.0.2.RELEASE'
}
}
这种方法集中管理版本,包括传递依赖项。
声明动态版本
在许多情况下,您可能需要使用特定模块依赖项的最新版本,或某个版本范围内的最新版本。这在开发过程中或创建需要与各种依赖项版本兼容的库时通常是必要的。项目可能会采用更积极的方式使用依赖项,始终集成最新版本以访问尖端功能。
您可以通过使用动态版本轻松管理这些不断变化的依赖项。动态版本可以是版本范围(例如,2.+
)或最新可用版本的占位符(例如,latest.integration
)
plugins {
`java-library`
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework:spring-web:5.+")
}
plugins {
id 'java-library'
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework:spring-web:5.+'
}
使用动态版本和变更模块可能导致不可重现的构建。随着模块新版本的发布,其 API 可能与您的源代码不兼容。因此,请谨慎使用此功能。
声明变更版本
一个团队可能会在发布应用程序或库的新版本之前实现一系列功能。一种常见的策略是发布一个带有变更版本的模块,以允许消费者尽早集成其未完成的工件。变更版本表示功能集仍在积极开发中,尚未发布稳定的通用版本。
在 Maven 仓库中,变更版本通常被称为快照版本。快照版本包含后缀 -SNAPSHOT
。
以下示例演示了如何在 Spring 依赖项上声明快照版本
plugins {
`java-library`
}
repositories {
mavenCentral()
maven {
url = uri("https://repo.spring.io/snapshot/")
}
}
dependencies {
implementation("org.springframework:spring-web:5.0.3.BUILD-SNAPSHOT")
}
plugins {
id 'java-library'
}
repositories {
mavenCentral()
maven {
url = 'https://repo.spring.io/snapshot/'
}
}
dependencies {
implementation 'org.springframework:spring-web:5.0.3.BUILD-SNAPSHOT'
}
Gradle 足够灵活,可以将任何版本视为变更版本。您只需将属性 ExternalModuleDependency.setChanging(boolean) 设置为 true
。