1. 概述
在这个教程中,我们将学习如何在Gradle项目中配置条件依赖。
2. 项目设置
我们将为演示创建一个多模块项目。请访问Spring Initializr,创建我们的根项目conditional-dependency-demo
。我们将使用Gradle、Java以及Spring Boot。
我们还会添加两个提供者模块provider1
和provider2
,以及两个消费者模块consumer1
和consumer2
:
3. 配置条件依赖
假设基于项目属性,我们希望包含两个提供者模块中的一个。对于consumer1
模块,如果指定了isLocal
属性,则包含provider1
模块。否则,应包含provider2
模块。
要在consumer1
模块的gradle.settings.kts
文件中实现这一点,请添加以下内容:
plugins {
id("java")
}
group = "com.baeldung.gradle"
version = "0.0.1-SNAPSHOT"
repositories {
mavenCentral()
}
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testRuntimeOnly ("org.junit.jupiter:junit-jupiter-engine:5.7.0")
if (project.hasProperty("isLocal")) {
implementation("com.baeldung.gradle:provider1")
} else {
implementation("com.baeldung.gradle:provider2")
}
}
tasks.getByName<Test>("test") {
useJUnitPlatform()
}
现在运行dependencies
任务查看选择了哪个提供者模块:
gradle -PisLocal dependencies --configuration implementation
> Task :consumer1:dependencies
------------------------------------------------------------
Project ':consumer1'
------------------------------------------------------------
implementation - Implementation only dependencies for source set 'main'. (n)
\--- com.baeldung.gradle:provider1 (n)
(n) - Not resolved (configuration is not meant to be resolved)
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 591ms
1 actionable task: 1 executed
如我们所见,传递了属性导致包含了provider1
模块。现在不指定任何属性运行dependencies
任务:
gradle dependencies --configuration implementation
> Task :consumer1:dependencies
------------------------------------------------------------
Project ':consumer1'
------------------------------------------------------------
implementation - Implementation only dependencies for source set 'main'. (n)
\--- com.baeldung.gradle:provider2 (n)
(n) - Not resolved (configuration is not meant to be resolved)
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 649ms
1 actionable task: 1 executed
正如我们所见,现在provider2
被包含。
4. 通过模块替换配置条件依赖
让我们看看另一种通过依赖替换来条件配置依赖的方法。对于consumer2
模块,如果指定了isLocal
属性,我们想要包含provider2
模块。否则,应使用provider1
模块。
为了实现这个目标,我们需要在consumer2
模块中添加以下配置:
plugins {
id("java")
}
group = "com.baeldung.gradle"
version = "0.0.1-SNAPSHOT"
repositories {
mavenCentral()
}
configurations.all {
resolutionStrategy.dependencySubstitution {
if (project.hasProperty("isLocal"))
substitute(project("com.baeldung.gradle:provider1"))
.using(project(":provider2"))
.because("Project property override(isLocal).")
}
}
dependencies {
implementation(project(":provider1"))
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
}
tasks.getByName<Test>("test") {
useJUnitPlatform()
}
再次运行相同的命令,我们应该得到类似的结果。首先,带isLocal
属性运行:
gradle -PisLocal dependencies --configuration compilePath
> Task :consumer2:dependencies
------------------------------------------------------------
Project ':consumer2'
------------------------------------------------------------
compileClasspath - Compile classpath for source set 'main'.
\--- project :provider1 -> project :provider2
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
确实,我们看到provider1
项目被替换为provider2
项目。现在不指定属性试一下:
gradle dependencies --configuration compilePath
> Task :consumer2:dependencies
------------------------------------------------------------
Project ':consumer2'
------------------------------------------------------------
compileClasspath - Compile classpath for source set 'main'.
\--- project :provider1
A web-based, searchable dependency report is available by adding the --scan option.
BUILD SUCCESSFUL in 623ms
1 actionable task: 1 executed
正如预期,这次没有替换发生,provider1
被包含。
5. 两种方法之间的差异
如上所述演示,两种方法都帮助我们实现了有条件地配置依赖的目标。让我们讨论一下两种方法之间的一些差异。
首先,直接在配置中编写条件逻辑看起来更简单,配置也较少,与第二种方法相比。
其次,尽管第二种方法涉及更多的配置,但它似乎更具语义性。 在第二种方法中,我们利用了Gradle本身提供的替换机制。它还允许我们指定替换的原因。此外,在日志中,我们可以注意到替换过程的发生,而在第一种方法中,这种信息是不可见的:
compileClasspath - Compile classpath for source set 'main'.
\--- project :provider1 -> project :provider2
请注意,在第一种方法中,不需要进行依赖解析。仅通过以下命令即可获取结果:
gradle -PisLocal dependencies --configuration implementation
而在第二种方法中,如果我们检查implementation
配置,将不会看到预期的结果。原因在于它只在依赖解析时工作。因此,它在compilePath
配置中可用:
gradle -PisLocal dependencies --configuration compilePath
6. 总结
至此,本文已结束。在这篇文章中,我们了解了在Gradle中配置条件依赖的两种方法,并分析了它们之间的区别。
Gradle提供的依赖替换配置似乎更为常用。如往常一样,完整的代码和Gradle配置可在GitHub上找到。