Appearance
工作原理
深入理解 Gradle 的工作原理,有助于编写更高效的构建脚本,排查构建问题。
整体架构
┌─────────────────────────────────────────┐
│ Gradle 构建 │
│ │
│ settings.gradle.kts │
│ ↓ 初始化阶段 │
│ build.gradle.kts × N │
│ ↓ 配置阶段 │
│ Task DAG(有向无环图) │
│ ↓ 执行阶段 │
│ 执行选中的 Task │
└─────────────────────────────────────────┘三阶段详解
阶段一:初始化(Initialization)
触发时机:每次运行 gradle 命令时
执行内容:
- 查找
settings.gradle.kts(从当前目录向上查找) - 解析
settings.gradle.kts,确定参与构建的项目列表 - 为每个项目创建
Project实例
kotlin
// settings.gradle.kts 的典型内容
pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
}
}
rootProject.name = "my-app"
// 多项目时声明子项目
include("core", "web", "service:auth", "service:order")阶段二:配置(Configuration)
触发时机:初始化完成后,每次运行 gradle 命令时
执行内容:
- 按顺序执行每个项目的
build.gradle.kts - 注册所有 Task(不执行,只注册)
- 构建 Task 依赖图(DAG)
性能陷阱
配置阶段所有项目的脚本都会执行,即使你只运行一个任务。 避免在配置阶段做耗时操作:
kotlin
// ❌ 错误:配置阶段执行耗时操作
tasks.register("myTask") {
val result = callExternalAPI() // 每次构建都调用,很慢
doLast { println(result) }
}
// ✅ 正确:在执行阶段做耗时操作
tasks.register("myTask") {
doLast {
val result = callExternalAPI() // 只在任务执行时调用
println(result)
}
}阶段三:执行(Execution)
触发时机:配置阶段完成后
执行内容:
- 根据命令行参数确定要执行的 Task
- 按 DAG 顺序执行 Task(依赖的 Task 先执行)
- 检查增量构建(跳过输入/输出未变更的 Task)
- 查询构建缓存(有缓存则直接使用)
任务有向无环图(DAG)
build
├── assemble
│ └── jar
│ └── compileJava
│ └── processResources
└── check
└── test
└── compileTestJava
└── compileJavabash
# 查看任务依赖关系
gradle build --dry-run
# 输出示例:
# :compileJava SKIPPED
# :processResources SKIPPED
# :classes SKIPPED
# :jar SKIPPED
# :compileTestJava SKIPPED
# :processTestResources SKIPPED
# :testClasses SKIPPED
# :test SKIPPED
# :check SKIPPED
# :assemble SKIPPED
# :build SKIPPED增量构建(Incremental Build)
Gradle 通过跟踪 Task 的**输入(Inputs)和输出(Outputs)**来决定是否需要重新执行。
kotlin
tasks.register<Copy>("copyDocs") {
from("src/docs") // 输入:源目录
into("$buildDir/docs") // 输出:目标目录
}判断逻辑:
- 输入文件没有变化
- 输出文件存在且与上次构建一致
- → Task 标记为
UP-TO-DATE,跳过执行
bash
$ gradle copyDocs
> Task :copyDocs
$ gradle copyDocs
> Task :copyDocs UP-TO-DATE ← 第二次执行,直接跳过构建缓存(Build Cache)
构建缓存比增量构建更进一步:即使在不同机器上,也可以复用构建结果。
本地缓存:~/.gradle/caches/
远程缓存:Gradle Enterprise / 自定义 HTTP 服务器bash
# 启用构建缓存
gradle build --build-cache
# 或在 gradle.properties 中永久启用
org.gradle.caching=true缓存 Key 的计算:
- Task 类型
- Task 输入(文件内容哈希、属性值)
- Gradle 版本
- JVM 版本
配置缓存(Configuration Cache)
Gradle 8+ 支持配置缓存,将配置阶段的结果缓存起来,下次跳过配置阶段。
bash
# 启用配置缓存
gradle build --configuration-cache
# 或在 gradle.properties 中启用
org.gradle.configuration-cache=truebash
# 第一次(需要配置)
$ gradle build
Calculating task graph as no cached configuration is available for tasks: build
...
Configuration cache entry stored.
# 第二次(使用缓存)
$ gradle build
Reusing configuration cache.
...
BUILD SUCCESSFULGradle Wrapper 机制
Gradle Wrapper 确保所有开发者使用相同版本的 Gradle,无需手动安装。
项目根目录/
├── gradlew ← Linux/macOS 脚本
├── gradlew.bat ← Windows 脚本
└── gradle/
└── wrapper/
├── gradle-wrapper.jar ← Wrapper 启动器
└── gradle-wrapper.properties ← 版本配置properties
# gradle-wrapper.properties
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists工作流程:
- 执行
./gradlew build - Wrapper 检查
~/.gradle/wrapper/dists/中是否有指定版本 - 没有则自动下载
- 使用下载的 Gradle 执行构建
依赖解析过程
声明依赖
↓
查询依赖图(递归解析传递依赖)
↓
版本冲突解决(选择最高版本/指定版本)
↓
查询本地缓存(~/.gradle/caches/)
↓ 缓存未命中
从仓库下载(Maven Central 等)
↓
存入本地缓存
↓
放入编译/运行 classpath守护进程(Gradle Daemon)
Gradle Daemon 是一个后台 JVM 进程,保持 Gradle 热加载状态,大幅加快构建速度。
bash
# 查看守护进程状态
gradle --status
# 停止所有守护进程
gradle --stop配置:
properties
# gradle.properties
org.gradle.daemon=true # 默认开启
org.gradle.daemon.idletimeout=10800000 # 闲置 3 小时后退出下一步
- Gradle vs Maven - 对比两种构建工具
- 安装与配置 - 开始动手实践