如何在 Gradle 中排除传递性依赖
本指南解释了如何在不需要或引起冲突时从项目中排除传递性依赖。
为什么排除传递性依赖?
排除传递性依赖应是一个有意识的决定,因为如果某个库依赖于被移除的依赖项,移除它们可能会导致运行时错误。
在排除之前,请确保
-
您的应用程序不需要被排除的依赖项。
-
您有足够的测试覆盖率来验证排除该依赖项不会破坏功能。
排除在以下情况有用:
-
一个库包含了应用程序不需要的不必要的传递性依赖。
-
您需要减少依赖项的大小。
-
存在依赖冲突且必须以不同方式解决。
步骤 1: 使用 exclude()
排除传递性依赖
首先,您必须找到导致使用不需要的传递性依赖项的依赖项。您可以使用 dependencies
任务来查找。
在本例中,我们要移除 commons-collections
依赖项
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4")
}
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4")
}
运行 ./gradlew dependencies --configuration runtimeClasspath
展示了 commons-collections
如何通过 commons-beanutils
引入
> Task :dependencies
------------------------------------------------------------
Root project 'how_to_exclude_transitive_dependencies'
------------------------------------------------------------
runtimeClasspath - Runtime classpath of source set 'main'.
\--- commons-beanutils:commons-beanutils:1.9.4
+--- commons-logging:commons-logging:1.2
\--- commons-collections:commons-collections:3.2.2
您可以通过在 exclude()
规则中指定 group
和 module
属性来针对每个依赖声明排除传递性依赖
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude(group = "commons-collections", module = "commons-collections")
}
}
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude group: "commons-collections", module: "commons-collections"
}
}
-
这会从
commons-beanutils
的传递性依赖项中移除commons-collections
。 -
该排除仅适用于这个特定的依赖项(即
commons-beanutils
)。
运行 ./gradlew dependencies --configuration runtimeClasspath
展示结果
> Task :dependencies
------------------------------------------------------------
Root project 'how_to_exclude_transitive_dependencies'
------------------------------------------------------------
runtimeClasspath - Runtime classpath of source set 'main'.
\--- commons-beanutils:commons-beanutils:1.9.4
\--- commons-logging:commons-logging:1.2
如果您的应用程序仅使用了库中不需要被排除依赖项的子集,则此方法是安全的。
步骤 2: 理解排除的影响
排除仅在所有依赖声明都同意排除时才生效。如果您的项目中另一个依赖项仍然需要被排除的依赖项,Gradle 将不会排除它。
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude(group = "commons-collections", module = "commons-collections")
}
implementation("com.opencsv:opencsv:4.6") // Depends on 'commons-beanutils' but does NOT exclude 'commons-collections'
}
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude group: "commons-collections", module: "commons-collections"
}
implementation("com.opencsv:opencsv:4.6") // Depends on 'commons-beanutils' but does NOT exclude 'commons-collections'
}
在这种情况下,commons-collections
仍然被包含,因为 opencsv
重新引入了它。
运行 ./gradlew dependencies --configuration runtimeClasspath
展示结果
> Task :dependencies
------------------------------------------------------------
Root project 'how_to_exclude_transitive_dependencies'
------------------------------------------------------------
runtimeClasspath - Runtime classpath of source set 'main'.
+--- commons-beanutils:commons-beanutils:1.9.4
| +--- commons-logging:commons-logging:1.2
| \--- commons-collections:commons-collections:3.2.2
\--- com.opencsv:opencsv:4.6
+--- org.apache.commons:commons-lang3:3.8.1
+--- org.apache.commons:commons-text:1.3
| \--- org.apache.commons:commons-lang3:3.7 -> 3.8.1
+--- commons-beanutils:commons-beanutils:1.9.3 -> 1.9.4 (*)
\--- org.apache.commons:commons-collections4:4.2
为了完全排除 commons-collections
,您也必须从 opencsv
中排除它。
步骤 3: 为多个依赖项排除传递性依赖
您必须对任何附加的依赖项重复步骤 1
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude(group = "commons-collections", module = "commons-collections")
}
implementation("com.opencsv:opencsv:4.6") {
exclude(group = "commons-collections", module = "commons-collections")
exclude(group = "org.apache.commons", module = "commons-collections4") // Watch out for other transitive dependency creep
}
}
dependencies {
implementation("commons-beanutils:commons-beanutils:1.9.4") {
exclude group: "commons-collections", module: "commons-collections"
}
implementation("com.opencsv:opencsv:4.6") {
exclude group: "commons-collections", module: "commons-collections"
exclude group: "org.apache.commons", module: "commons-collections4" // Watch out for other transitive dependency creep
}
}
本例实际上更进一步,因为 com.opencsv:opencsv
实际上引入了 commons-collections4
。
现在,commons-collections
和 commons-collections4
已从所有引用它们的依赖项中完全排除
> Task :dependencies
------------------------------------------------------------
Root project 'how_to_exclude_transitive_dependencies'
------------------------------------------------------------
runtimeClasspath - Runtime classpath of source set 'main'.
+--- commons-beanutils:commons-beanutils:1.9.4
| \--- commons-logging:commons-logging:1.2
\--- com.opencsv:opencsv:4.6
+--- org.apache.commons:commons-lang3:3.8.1
+--- org.apache.commons:commons-text:1.3
| \--- org.apache.commons:commons-lang3:3.7 -> 3.8.1
\--- commons-beanutils:commons-beanutils:1.9.3 -> 1.9.4 (*)