直接依赖项与依赖项约束

一个组件可能有两种不同的依赖项

  • 直接依赖项是组件直接需要的。直接依赖项也称为一级依赖项。例如,如果你的项目源代码需要 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-codec 作为传递依赖项引入时才会考虑,因为 commons-codec 未在项目中定义为依赖项。否则,约束无效。依赖项约束还可以定义 丰富版本约束 并支持 严格版本,即使它与传递依赖项定义的版本相矛盾(例如,如果需要降级版本)。

仅在使用 Gradle 模块元数据 时才会发布依赖项约束。这意味着目前仅在将 Gradle 用于发布和使用时才完全支持它们(即在使用 Maven 或 Ivy 使用模块时“丢失”)。

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