Skip to content

版本冲突解决

当多个依赖引入同一库的不同版本时,就会产生版本冲突。Gradle 默认使用最高版本胜出策略。

默认策略:最高版本

A 依赖 guava:30.0
B 依赖 guava:32.0
→ Gradle 自动选择 guava:32.0(高版本优先)
bash
# 查看冲突及解决结果
./gradlew dependencies --configuration compileClasspath

# 输出中 (*) 表示被省略的重复依赖,-> 表示版本被升级
# +--- com.example:A:1.0
# |    \--- com.google.guava:guava:30.0 -> 32.0 (*)  ← 升级到 32.0
# \--- com.example:B:1.0
#      \--- com.google.guava:guava:32.0

强制指定版本

kotlin
// 方式一:在 dependencies 中强制
dependencies {
    implementation("com.fasterxml.jackson.core:jackson-databind") {
        version { strictly("2.15.3") }
    }
}

// 方式二:resolutionStrategy(全局)
configurations.all {
    resolutionStrategy {
        force("com.fasterxml.jackson.core:jackson-databind:2.15.3")
        force(
            "org.slf4j:slf4j-api:2.0.9",
            "ch.qos.logback:logback-classic:1.4.11"
        )
    }
}

失败策略(严格模式)

kotlin
configurations.all {
    resolutionStrategy {
        // 发生版本冲突时构建失败(而非自动升级)
        failOnVersionConflict()
    }
}

依赖替换

kotlin
configurations.all {
    resolutionStrategy.dependencySubstitution {
        // 替换某个依赖为另一个
        substitute(module("com.google.guava:guava-jdk5"))
            .using(module("com.google.guava:guava:32.0.1-jre"))
        
        // 使用本地项目替换外部依赖(复合构建常用)
        substitute(module("com.example:my-lib"))
            .using(project(":my-lib"))
    }
}

查看具体冲突来源

bash
# 查看 guava 被哪些依赖引入
./gradlew dependencyInsight --dependency guava

# 输出:
# com.google.guava:guava:32.0.1-jre (selected by rule)
#    Variant compileClasspath:
#    | Attribute Name     | Values  |
#    +--------------------+---------+
#    | ...                |         |
# 
# com.google.guava:guava:30.0 -> 32.0.1-jre
# +--- com.example:A:1.0
#      \--- compileClasspath

约束(Constraints)

kotlin
dependencies {
    // 添加版本约束(不引入依赖,只约束版本)
    constraints {
        implementation("com.google.guava:guava:32.0.1-jre") {
            because("避免安全漏洞 CVE-2023-2976")
        }
    }
    
    implementation("com.example:A:1.0")  // A 的传递依赖 guava 会被约束到 32.0.1
}

下一步