Gradle依赖冲突必须显式干预,因默认选最新版;force可强制覆盖传递依赖版本,constraints语义更清晰且冲突报错,exclude精准剔除特定路径依赖,resolutionStrategy可全局禁用问题版本范围。

不能靠“不写那个版本”来禁止——Gradle 默认会选最新版,必须显式干预。
用 force 强制覆盖传递依赖的版本
当某个第三方库(比如 com.example:lib-a:1.2.0)偷偷带入了你明知有问题的 org.bad:broken:3.1.0,而你自己又没直接声明它时,force 是最直接的拦截方式。
-
force会覆盖整个依赖图中对该模块的所有版本请求,不管它从哪来 - 只在当前配置块生效,如需全局生效,得套在
configurations.all里 - Gradle 5.0+ 更推荐用
constraints替代全局force,语义更清晰、冲突时会报错而非静默覆盖
Groovy DSL 示例:
dependencies {
implementation 'com.example:lib-a:1.2.0'
constraints {
implementation('org.bad:broken') {
version {
strictly '2.9.0'
}
because '3.1.0 has NPE in init()'
}
}
}
Kotlin DSL 示例:
dependencies {
implementation("com.example:lib-a:1.2.0")
constraints {
implementation("org.bad:broken") {
version {
strictly("2.9.0")
}
because("3.1.0 has NPE in init()")
}
}
}
用 exclude 彻底移除有问题的依赖路径
如果那个坏版本只出现在某条特定传递路径上(比如仅由 com.example:lib-b 引入),且你根本不需要它,exclude 比 force 更轻量、副作用更小。
-
exclude只作用于紧邻的父依赖,不会影响其他路径引入的同名模块 - 支持按
group、module,甚至classifier精准剔除(例如排除snakeyaml-2.0-android.jar) - 不能在
libs.versions.toml中写exclude—— 版本目录只管坐标和版本,不参与依赖图裁剪
错误写法(无效):
[libraries]
broken = { module = "org.bad:broken", version = "3.1.0" }
# 这里加 exclude 会被忽略
正确写法(在 build.gradle 中):
implementation('com.example:lib-b:2.0.0') {
exclude group: 'org.bad', module: 'broken'
}
用 resolutionStrategy 全局禁止某版本范围
当你发现某个组织下多个模块都发布了带 bug 的快照版或预发布版(比如 org.bad:* 的所有 -alpha 或 -SNAPSHOT),可以一次性封禁整类版本。
-
resolutionStrategy在configurations级别生效,适合在根build.gradle统一管控 - 配合
failOnVersionConflict()能让构建在遇到被禁版本时立刻失败,而不是降级或忽略 - 注意:它不阻止下载,只阻止解析;若本地缓存已有该版本,仍可能被复用
示例(禁止所有 org.bad 下的 -SNAPSHOT):
configurations.all {
resolutionStrategy {
force 'org.bad:broken:2.9.0'
// 或更严格地拒绝非法版本
reject 'org.bad:broken:*-SNAPSHOT'
failOnVersionConflict()
}
}
真正难处理的不是“怎么写语法”,而是确认哪个版本真的不能用——得靠 ./gradlew dependencyInsight --dependency org.bad:broken 看清它从哪来、被谁拉进来、有没有替代方案。否则强行 force 或 exclude,可能让某个库悄悄失能。











