本指南解释了当您的项目由于 API 兼容性、错误或其他限制需要旧版本时,如何在 Gradle 中降级传递性依赖

为什么要降级传递性依赖?

默认情况下,Gradle 通过选择依赖图中最新版本来解决依赖版本冲突。但是,在某些情况下需要使用旧版本。

  • 最新版本中存在错误

  • 您的项目依赖于与新版本不兼容的旧 API

  • 您的代码不需要要求更高版本的功能。

在降级之前,请考虑更新您的源代码以支持最新版本。

此外,您应该确保项目中不存在已有的依赖约束平台版本目录,它们将依赖设置为不需要的版本。

如果降级是必要的,请使用严格依赖强制依赖

选项 1:强制执行依赖的严格版本

Gradle 允许您强制执行依赖的严格版本,确保所选版本不能被传递性依赖升级。

步骤 1:设置严格版本

假设一个项目依赖于 HttpClient,它引入了 Commons Codec 1.10,但您的项目需要 Commons Codec 1.9

dependencies.out
> Task :dependencies

------------------------------------------------------------
Root project 'how_to_downgrade_transitive_dependencies'
------------------------------------------------------------

runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.apache.httpcomponents:httpclient:4.5.4
|    +--- org.apache.httpcomponents:httpcore:4.4.7
|    +--- commons-logging:commons-logging:1.2
|    \--- commons-codec:commons-codec:1.10
\--- commons-codec:commons-codec -> 1.10

您可以通过设置严格版本约束来强制执行所需版本。

build.gradle.kts
dependencies {
    implementation("org.apache.httpcomponents:httpclient:4.5.4")
    implementation("commons-codec:commons-codec") {
        version {
            strictly("1.9")
        }
    }
}
build.gradle
dependencies {
    implementation("org.apache.httpcomponents:httpclient:4.5.4")
    implementation("commons-codec:commons-codec") {
        version {
            strictly("1.9")
        }
    }
}

运行./gradlew dependencies --configuration runtimeClasspath显示结果

dependencies-downgrade.out
> Task :dependencies

------------------------------------------------------------
Root project 'how_to_downgrade_transitive_dependencies'
------------------------------------------------------------

runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.apache.httpcomponents:httpclient:4.5.4
|    +--- org.apache.httpcomponents:httpcore:4.4.7
|    +--- commons-logging:commons-logging:1.2
|    \--- commons-codec:commons-codec:1.10 -> 1.9
\--- commons-codec:commons-codec:{strictly 1.9} -> 1.9

关于严格版本的重要说明

  • 严格版本表现得像一个强制,这意味着它会覆盖传递性依赖。

  • 如果另一个依赖需要更高版本,Gradle 将以解析错误失败

  • 使用版本范围而不是绝对严格版本以允许灵活性。

步骤 2:设置严格版本范围

不要锁定到单个版本,而是定义一个严格范围

build.gradle.kts
dependencies {
    implementation("commons-codec:commons-codec") {
        version {
            strictly("[1.9,2.0[")  // Allows versions >=1.9 and <2.0
            prefer("1.9")  // Prefers 1.9 but allows newer versions in range
        }
    }
}
build.gradle
dependencies {
    implementation("commons-codec:commons-codec") {
        version {
            strictly("[1.9,2.0[")  // Allows versions >=1.9 and <2.0
            prefer("1.9")  // Prefers 1.9 but allows newer versions in range
        }
    }
}

如果另一个依赖需要 1.10,只要它落在指定范围内,Gradle 就可以成功解析它。

dependencies-extra.out
> Task :dependencies

------------------------------------------------------------
Root project 'how_to_downgrade_transitive_dependencies'
------------------------------------------------------------

runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.apache.httpcomponents:httpclient:4.5.4
|    +--- org.apache.httpcomponents:httpcore:4.4.7
|    +--- commons-logging:commons-logging:1.2
|    \--- commons-codec:commons-codec:1.10 -> 1.9
\--- commons-codec:commons-codec:{strictly [1.9,2.0[; prefer 1.9} -> 1.9

选项 2:在配置级别强制指定版本

如果严格依赖限制性太强,您可以使用resolutionStrategy.force()为整个配置强制指定特定版本。

步骤 1:为整个构建强制指定版本

build.gradle.kts
configurations {
    compileClasspath {
        resolutionStrategy.force("commons-codec:commons-codec:1.9")
    }
}

dependencies {
    implementation("org.apache.httpcomponents:httpclient:4.5.4")
}
build.gradle
configurations {
    compileClasspath {
        resolutionStrategy.force("commons-codec:commons-codec:1.9")
    }
}

dependencies {
    implementation("org.apache.httpcomponents:httpclient:4.5.4")
}

运行./gradlew dependencies --configuration compileClasspath显示结果。

dependencies-config.out
> Task :dependencies

------------------------------------------------------------
Root project 'how_to_downgrade_transitive_dependencies'
------------------------------------------------------------

compileClasspath - Compile classpath for source set 'main'.
\--- org.apache.httpcomponents:httpclient:4.5.4
     +--- org.apache.httpcomponents:httpcore:4.4.7
     +--- commons-logging:commons-logging:1.2
     \--- commons-codec:commons-codec:1.10 -> 1.9

这确保始终使用 Commons Codec 1.9,即使传递性依赖请求新版本。

总结

回顾两种选项

方法 行为

1. 严格版本 (strictly())

版本被强制执行,但如果存在冲突可能会触发解析失败。

2. 强制版本 (force())

版本在配置级别强制应用,覆盖所有其他约束。

总结

  • 如果您需要强制使用旧版本并希望控制兼容性,请使用严格版本

  • 使用具有首选版本的版本范围以允许一定的灵活性。

  • 当您需要覆盖传递性依赖而没有严格约束时,在配置级别使用force()