Direct dependencies vs dependency constraints

组件可能具有两种不同的依赖关系:

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

  • 传递依赖关系是组件所需的依赖关系,但这仅是因为另一个依赖关系需要它们.

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

Adding constraints on transitive dependencies

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

例子1.定义依赖关系约束
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'
        }
    }
}
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")
        }
    }
}

在该示例中,所有版本都从依赖声明中省略. 而是在约束块中定义版本. 如果将commons-codec作为传递依赖项引入,则仅考虑commons-codec:1.11的版本定义,因为在项目中没有将commons-codec定义为依赖项. 否则,约束无效. 依赖关系约束还可以定义丰富的版本约束,并支持严格的版本以强制执行版本,即使它与传递依赖关系定义的版本相矛盾(例如,如果版本需要降级).

依赖关系约束仅在使用Gradle Module元数据时发布. 这意味着当前仅在使用Gradle进行发布和使用时才完全支持它们(即,当使用Maven或Ivy使用模块时,它们"丢失"了).

依赖性约束本身也可以传递地添加.