直接依赖与依赖约束

一个组件可能有两种不同类型的依赖关系:

  • 直接依赖项是组件直接需要的。直接依赖性也称为第一级依赖性。例如,如果您的项目源代码需要 Guava,则应将 Guava 声明为直接依赖

  • 传递依赖项是您的组件需要的依赖项,但只是因为另一个依赖项需要它们。

依赖管理的问题与传递依赖有关,这是很常见的。开发人员常常通过添加直接依赖项来错误地修复传递依赖项问题。为了避免这种情况,Gradle 提供了依赖约束的概念。

添加传递依赖的约束

依赖项约束允许您定义构建脚本中声明的依赖项和传递依赖项的版本或版本范围。它是表达应应用于配置的所有依赖项的约束的首选方法。当 Gradle 尝试解析对模块版本的依赖关系时,会考虑该模块的所有依赖关系声明、所有传递依赖关系以及该模块的所有依赖关系约束。选择符合所有条件的最高版本。如果找不到这样的版本,Gradle 将失败并显示冲突声明的错误。如果发生这种情况,您可以调整依赖项或依赖项约束声明,或者根据需要对传递依赖项进行其他调整。与依赖项声明类似,依赖项约束声明的范围由配置决定,因此可以为构建的各个部分选择性地定义。如果依赖性约束影响了解析结果,则之后仍可以应用任何类型的依赖性解析规则。

build.gradle.kts
dependencies {
    implementation("org.apache.httpcomponents:httpclient")
    constraints {
        implementation("org.apache.httpcomponents:httpclient:4.5.3") {
            because("previous versions have a bug impacting this application")
        }
        implementation("commons-codec:commons-codec:1.11") {
            because("version 1.9 pulled from httpclient has bugs affecting this application")
        }
    }
}
build.gradle
dependencies {
    implementation 'org.apache.httpcomponents:httpclient'
    constraints {
        implementation('org.apache.httpcomponents:httpclient:4.5.3') {
            because 'previous versions have a bug impacting this application'
        }
        implementation('commons-codec:commons-codec:1.11') {
            because 'version 1.9 pulled from httpclient has bugs affecting this application'
        }
    }
}

在示例中,依赖项声明中省略了所有版本。相反,版本是在约束块中定义的。仅当作为传递依赖项引入commons-codec:1.11时,才会考虑的版本定义,因为在项目中未定义为依赖项。否则,约束无效。依赖约束还可以定义丰富的版本约束并支持严格版本来强制执行版本,即使它与传递依赖定义的版本相矛盾(例如,如果版本需要降级)。commons-codeccommons-codec

仅当使用Gradle 模块元数据 时才会发布依赖关系约束。这意味着目前只有当 Gradle 用于发布和使用时它们才得到完全支持(即当使用 Maven 或 Ivy 消费模块时它们会“丢失”)。

依赖约束本身也可以被传递地添加。