如何在 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 (*)