30、Gradle高级主题:复合构建、Gradle Modules、自定义构建逻辑与未来展望

各位同学,欢迎来到第三十讲。走到这里,Gradle 的核心知识你已经掌握得差不多了。今天我们来聊聊那些真正让 Gradle 变得“高级”的东西——复合构建、模块化、自定义逻辑,以及 Gradle 9.x 的新方向。

说实话,这些内容在日常小项目中可能用不上。但一旦你开始维护大型项目、多模块仓库,或者需要构建一套公司级的构建规范,这些就是你的“杀手锏”。

复合构建(Composite Build)

先问一个问题:你手头有两个独立的 Gradle 项目,一个是你正在开发的业务库,另一个是你们团队维护的公共工具库。你想在业务库里直接调试工具库的最新代码,怎么办?

传统做法是把工具库发布到本地 Maven 仓库,然后业务库引用。每次改完工具库,都要 publishToMavenLocal,再刷新业务库。太慢了。

复合构建就是来解决这个问题的。

它允许你把多个独立的 Gradle 项目“组合”在一起,让它们像一个项目一样互相依赖。你可以在业务库的 settings.gradle 里这样写:

// settings.gradle
rootProject.name = 'my-business-app'

includeBuild('../my-tool-library')

然后,在业务库的 build.gradle 里,直接引用工具库的模块:

dependencies {
    implementation('com.mycompany:my-tool-core:1.0.0') // 这个版本号会被复合构建覆盖
}

嗯,这里要注意:复合构建会“覆盖”你声明的版本号。Gradle 会优先使用被包含项目的实际代码,而不是从仓库里下载的 jar 包。

我的经验: 我在做微服务框架升级时,经常用复合构建来同时调试五六个子项目。改完一个库的代码,直接运行主项目的测试,所有依赖自动生效。省去了反复发布的痛苦。

复合构建的典型场景

  • 本地开发调试:同时修改多个关联项目
  • 插件开发:在宿主项目中直接调试自定义插件
  • 构建逻辑复用:把公共构建逻辑抽取为独立项目,通过复合构建引入

Gradle Modules 与模块化设计

说到模块化,很多人第一反应是 Java 9 的 module-info.java。但 Gradle 的模块化,更多是指构建层面的模块拆分

我个人习惯把项目拆成三层:

  • API 模块:只暴露接口和模型,不包含实现
  • Core 模块:核心业务逻辑,依赖 API 模块
  • App 模块:最终的可执行应用,依赖 Core 模块

这样做的好处是:依赖关系清晰,编译速度更快。因为 Gradle 可以并行构建互不依赖的模块。

举个例子,一个典型的 settings.gradle 是这样的:

rootProject.name = 'my-application'

include 'my-api'
include 'my-core'
include 'my-app'

// 还可以包含独立的构建逻辑模块
includeBuild('gradle/plugins')

每个模块的 build.gradle 只声明自己需要的依赖:

// my-core/build.gradle
dependencies {
    implementation project(':my-api')
    implementation 'com.google.guava:guava:32.1.3-jre'
}
避坑指南: 我曾经在一个大项目里,把所有模块的依赖都写在了根项目的 build.gradle 里,用 allprojects 统一声明。结果每次改一个模块的依赖,整个项目都要重新配置。后来我改成每个模块独立声明,配合 dependencyManagement 统一版本号,构建速度提升了 40%。

自定义构建逻辑

Gradle 最强大的地方,就是你可以用 Groovy 或 Kotlin 写自己的构建逻辑。说白了,Gradle 本身就是一个编程框架

常见的自定义方式有三种:

方式 适用场景 复杂度
buildSrc 单个项目内的自定义逻辑
复合构建 + 插件项目 跨项目复用构建逻辑
独立插件发布 公司级/开源级构建规范

我个人最推荐的是复合构建 + 插件项目的方式。你想想看,把构建逻辑放在 buildSrc 里,虽然方便,但没法跨项目复用。而发布独立插件又太重了,每次改个配置都要发版。

复合构建正好折中:

// 在 gradle/plugins 目录下创建一个独立的插件项目
// gradle/plugins/build.gradle.kts
plugins {
    `java-gradle-plugin`
}

gradlePlugin {
    plugins {
        register("my-conventions") {
            id = "com.mycompany.conventions"
            implementationClass = "com.mycompany.gradle.MyConventionsPlugin"
        }
    }
}

// 然后在主项目的 settings.gradle 里引入
includeBuild('gradle/plugins')

这样,你可以在插件项目里写任何复杂的构建逻辑,主项目直接 apply 即可。改完插件代码,不需要发布,直接运行主项目的任务就能生效。

核心要点: 自定义构建逻辑的核心是 TaskPlugin。Task 定义“做什么”,Plugin 定义“什么时候做”以及“需要哪些配置”。记住这个原则,你的构建逻辑就会清晰很多。

未来展望:Gradle 9.x 新特性

聊完了现在,我们看看未来。Gradle 9.x 有几个方向值得关注:

1. 更快的配置阶段

Gradle 8.x 已经引入了 配置缓存,9.x 会进一步优化。说白了,就是让 settings.gradlebuild.gradle 的解析速度更快。对于大型项目,配置阶段可能从几十秒缩短到几秒。

2. 更完善的 Kotlin DSL 支持

虽然现在 Kotlin DSL 已经很好用了,但 9.x 会进一步减少 Groovy 和 Kotlin 之间的行为差异。我个人建议,新项目直接用 Kotlin DSL,Groovy 的灵活性虽然高,但 IDE 支持和类型安全方面,Kotlin 明显更胜一筹。

3. 增量构建的进一步优化

Gradle 的增量构建已经很智能了,但 9.x 会引入更细粒度的输入跟踪。比如,以前你改了一个资源文件,整个 processResources 任务都要重跑。未来可能只重跑受影响的那部分。

4. 构建扫描的深度集成

构建扫描(Build Scan)现在是 Gradle 的标配。9.x 会把它更深度地集成到构建流程中,甚至可以在构建失败时自动生成诊断报告。

我的建议: 不要等到 9.x 正式发布才去学。现在就可以尝试 Gradle 8.x 的最新版本,很多 9.x 的特性已经在 8.x 里以“实验性”功能的形式出现了。比如 --configuration-cache 参数,你现在就可以用起来。

知识体系总览

为了帮你理清这一章的知识结构,我画了一张图:

Gradle 高级主题知识体系 复合构建 • 多项目组合调试 • 覆盖依赖版本号 • 本地开发利器 • 插件开发调试 Gradle Modules • API/Core/App 三层拆分 • 并行构建加速 • 依赖关系清晰 • 独立版本管理 自定义构建逻辑 • buildSrc 单项目复用 • 复合构建跨项目复用 • 独立插件发布 • Task + Plugin 核心 未来展望 9.x • 配置阶段加速 • Kotlin DSL 完善 • 增量构建优化 • 构建扫描深度集成 核心目标:构建更快、更灵活、更可维护

这张图把四个核心主题串在了一起。你会发现,它们其实都指向同一个目标:让构建过程更快、更灵活、更可维护

好了,这一讲的内容就到这里。复合构建和模块化设计,是我在实际项目中用得最多的技巧。如果你现在正在维护一个中型以上的项目,我强烈建议你试试复合构建——哪怕只是把插件代码抽出来单独管理,都会让你的构建逻辑清晰很多。

至于 Gradle 9.x,保持关注就好。Gradle 的迭代速度很快,但核心思想不会变:约定优于配置,灵活但不失严谨


公众号:蓝海资料掘金营,微信 deep3321