1. 概述
Gradle 6.0 的发布带来了多项关键改进,显著提升了构建的效率与稳定性。核心升级包括:依赖管理增强、模块元数据发布支持、任务配置延迟(Configuration Avoidance)以及对 JDK 13 的完整支持。
本文将系统性地介绍 Gradle 6.0 中这些实用新特性。示例代码统一采用 Kotlin DSL 编写,更符合现代 Gradle 项目的实践。
2. 依赖管理增强
近年来 Gradle 持续优化依赖管理机制,而 Gradle 6.0 正是这些演进的集大成者。以下特性均已稳定,可放心在生产环境使用。
2.1 API 与实现分离
java-library
插件的核心价值在于强制区分 公开 API 依赖 与 内部实现依赖。这能有效防止下游项目意外引用本应私有的类,从而提升构建稳定性。
虽然该插件早在 Gradle 3.4 就已引入,但其真正的威力在 Gradle 6.0 的完整依赖管理体系中才得以完全释放。
- ✅
api
: 声明的依赖会暴露给使用者(传递性依赖) - ✅
implementation
: 仅项目内部使用,使用者不会继承
dependencies {
api("com.fasterxml.jackson.core:jackson-databind:2.13.0") // 暴露给调用方
implementation("org.apache.commons:commons-lang3:3.12.0") // 私有依赖
}
⚠️ 踩坑提醒:滥用
api
会导致依赖传递爆炸,应严格遵循“最小暴露”原则。
2.2 丰富的版本声明(Rich Versions)
当依赖树中出现版本冲突时,Gradle 6.0 允许通过精细化版本策略指导解析逻辑,避免“最新版本优先”带来的潜在不兼容问题。
核心指令:
require
: 必须满足的最低版本prefer
: 优先选择的版本(无冲突时)strictly
: 严格限定版本范围reject
: 明确排除的版本because
: 添加注释说明(推荐)
场景示例:
你的项目使用 Guava,但仅依赖 10.0+ 的稳定 API,测试基于 28.1-jre。同时依赖的库 foo
强制使用 Guava 16.0。
dependencies {
implementation("com.google.guava:guava") {
version {
require("10.0")
prefer("28.1-jre")
because("依赖 10.0+ 的 API,测试环境为 28.1-jre")
}
}
}
✅ 效果:当与 foo
冲突时,Gradle 会选择 16.0(满足双方要求),而非简单选最新版 28.1。
进阶用法:规避已知问题
dependencies {
implementation("com.google.guava:guava") {
version {
strictly("[10.0, 28[") // 严格限定 10.0 <= v < 28
prefer("28.1-jre")
reject("27.0") // 已知 27.0 存在严重 Bug
because("""
API 在 10.0 引入,29.0 移除。27.0 版本有已知问题。
""".trimIndent())
}
}
}
2.3 平台(Platforms)统一依赖版本
java-platform
插件类似于 Maven 的 <dependencyManagement>
,用于集中管理一组依赖的版本号,避免多模块项目中版本不一致。
适用场景:
- 多模块微服务项目
- 统一技术栈(如 Spring Boot 版本)
- 第三方组件版本对齐(如 HTTP 客户端)
创建平台项目 httpclient-platform
:
// build.gradle.kts
plugins {
`java-platform`
}
dependencies {
constraints {
api("org.apache.httpcomponents:fluent-hc:4.5.10")
api("org.apache.httpcomponents:httpclient:4.5.10")
}
}
在业务模块中使用:
// build.gradle.kts
plugins {
`java-library`
}
dependencies {
api(platform(project(":httpclient-platform"))) // 引入平台
implementation("org.apache.httpcomponents:fluent-hc") // 无需指定版本
}
✅ 优势:版本升级只需修改平台项目,所有子模块自动同步。
2.4 测试夹具(Test Fixtures)
Gradle 6.0 新增 java-test-fixtures
插件,允许将测试辅助代码(如基类、测试数据、Mock 对象)作为独立构件发布,无需创建额外的 *-test
库。
使用场景:
- SPI(服务提供者接口)的契约测试
- 通用测试工具类
- 集成测试的公共配置
示例:为 Fibonacci 抽象定义测试夹具
- 创建
fibonacci-spi
项目: ```kotlin // build.gradle.kts plugins {java-library
java-test-fixtures
}
dependencies { testFixturesApi("org.junit.jupiter:junit-jupiter-api:5.8.1") testFixturesImplementation("org.junit.jupiter:junit-jupiter-engine:5.8.1") }
2. **编写测试夹具接口(位于 `src/testFixtures/java`):**
```java
public interface FibonacciSequenceGeneratorFixture {
FibonacciSequenceGenerator provide();
@Test
default void whenSequenceIndexIsNegative_thenThrows() {
FibonacciSequenceGenerator generator = provide();
assertThrows(IllegalArgumentException.class, () -> generator.generate(-1));
}
@Test
default void whenGivenIndex_thenGeneratesFibonacciNumber() {
FibonacciSequenceGenerator generator = provide();
int[] sequence = { 0, 1, 1, 2, 3, 5, 8 };
for (int i = 0; i < sequence.length; i++) {
assertEquals(sequence[i], generator.generate(i));
}
}
}
在实现项目
fibonacci-recursive
中复用:// build.gradle.kts dependencies { api(project(":fibonacci-spi")) testImplementation(testFixtures(project(":fibonacci-spi"))) // 关键:引用测试夹具 testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.1") testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.1") }
直接使用夹具:
class RecursiveFibonacciUnitTest implements FibonacciSequenceGeneratorFixture { @Override public FibonacciSequenceGenerator provide() { return new RecursiveFibonacci(); } }
✅ 价值:大幅减少重复测试代码,提升测试一致性。
3. Gradle 模块元数据发布
传统 Maven/pom.xml
和 Ivy 格式无法存储 Gradle 6.0 的丰富依赖信息(如 rich versions
、platforms
)。为解决此问题,Gradle 引入了 Gradle Module Metadata 规范。
核心要点:
- ✅ 格式:JSON 文件(
.module
后缀) - ✅ 兼容性:与
pom.xml
并存,不影响旧工具 - ✅ 内容:完整保留 Gradle 特有的依赖元数据
- ✅ 默认开启:使用新版
maven-publish
或ivy-publish
插件时自动发布
发布到 Maven 仓库
// build.gradle.kts
plugins {
`java-library`
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
}
}
}
执行发布:
./gradlew publishToMavenLocal
查看本地仓库:
ls ~/.m2/repository/com/baeldung/gradle-6/1.0.0/
# 输出:
# gradle-6-1.0.0.jar
# gradle-6-1.0.0.module # ✅ Gradle Module Metadata
# gradle-6-1.0.0.pom
⚠️ 注意:只有使用 Gradle 构建的项目才能消费
.module
文件中的增强元数据,Maven 项目仍只读pom.xml
。
4. 任务配置避免(Configuration Avoidance)
Gradle 构建的性能瓶颈常在于 任务配置阶段(即解析 build.gradle
时创建和配置所有任务)。Gradle 5.1 引入的 Configuration Avoidance API 在 6.0 正式稳定。
核心思想
延迟任务/配置的实例化,直到真正需要执行时才“实现”(realize),从而跳过大量无用配置。
迁移指南(关键替换)
旧写法 (立即配置) | 新写法 (延迟配置) | 优势 |
---|---|---|
tasks.create() |
tasks.register() |
任务未执行时不创建实例 |
tasks.getByName() |
tasks.named() |
返回 Provider<Task> ,延迟获取 |
configurations.create() |
configurations.register() |
延迟配置创建 |
File(project.buildDir, "foo") |
project.layout.buildDirectory.dir("foo") |
延迟路径解析 |
示例:注册延迟任务
val copyExtraLibs by tasks.registering(Copy::class) {
from("src/extralibs")
into(layout.buildDirectory.dir("extra-libs"))
}
registering
返回TaskProvider<Copy>
Copy
实例在任务真正执行前不会被创建from
/into
的配置闭包也延迟执行
✅ 效果:大型多模块项目构建脚本解析时间显著缩短。
5. JDK 13 支持
Gradle 6.0 正式支持使用 JDK 13 编译和运行项目。
基础配置
java {
sourceCompatibility = JavaVersion.VERSION_13
targetCompatibility = JavaVersion.VERSION_13
}
启用预览特性(Preview Features)
JDK 13 包含预览特性(如 Raw String Literals),需显式开启:
tasks {
compileJava {
options.compilerArgs.add("--enable-preview")
}
test {
jvmArgs("--enable-preview")
}
javadoc {
(options as CoreJavadocOptions).apply {
addStringOption("source", "13")
addBooleanOption("-enable-preview", true)
}
}
}
⚠️ 警告:预览特性不保证向后兼容,生产环境慎用。
6. 总结
Gradle 6.0 是一次以 构建稳定性 和 性能 为核心的升级:
- ✅ 依赖管理:通过
rich versions
和platforms
精细化控制依赖解析。 - ✅ 元数据发布:
.module
文件让下游 Gradle 项目能继承完整依赖策略。 - ✅ 配置避免:
register
等 API 显著优化大型项目的构建性能。 - ✅ JDK 支持:无缝对接 JDK 13,包括预览特性。
这些特性共同构成了现代 Gradle 项目的最佳实践基础。建议新项目直接采用,存量项目可逐步迁移。
本文示例代码详见 GitHub: https://github.com/baeldung/tutorials/tree/master/gradle-modules/gradle-6