Gradle 核心概念

FreeGuideOnline 最新 2026-07-15

kotlin // Kotlin DSL 示例 plugins { // 插件块 java application }

repositories { // 仓库配置 mavenCentral() }

dependencies { // 依赖配置 implementation("com.google.guava:guava:31.1-jre") }

application { // 插件提供的扩展配置 mainClass.set("com.example.Main") }


## 2. 任务(Task)—— 构建的基本工作单元

### 2.1 什么是任务

**任务**是 Gradle 中的原子工作单元,代表一次具体的操作,例如编译源代码、运行测试、打包 JAR 文件等。一个项目的整个构建过程由一系列有序执行的任务组成。

### 2.2 内置任务与自定义任务

插件通常会带来大量内置任务,你可以在命令行通过 `gradle tasks` 查看所有可用任务。你也可以轻松定义自己的任务:

```kotlin
tasks.register("hello") { // 注册一个新任务
    doLast {
        println("Hello, Gradle!")
    }
}

任务之间可以显式声明依赖关系,确定执行顺序:

val compile = tasks.named("compileJava")
tasks.register("myCustomTask") {
    dependsOn(compile) // 只有 compileJava 执行完后才执行本任务
    doLast { ... }
}

2.3 任务生命周期钩子

每个任务都提供 doFirstdoLast 闭包/代码块,用于在任务动作列表的首尾插入行为。这些钩子使得在不修改原有任务的情况下注入额外逻辑成为可能。

3. 构建生命周期

Gradle 执行构建时会经历三个固定的阶段:

  1. 初始化(Initialization)

    • 检测 settings.gradle(.kts) 文件,确定参与本次构建的所有项目(Project)。
    • 为每个项目创建一个 Project 实例(多项目时为层次结构)。
  2. 配置(Configuration)

    • 按顺序执行每个项目的构建脚本,配置项目对象。
    • 任务对象被创建和配置,但不会执行任何任务动作。
    • 整个依赖关系图在配置阶段末尾确定。
  3. 执行(Execution)

    • 运行用户在命令行中指定的任务(或默认任务),按依赖关系顺序执行。
    • 真正发生编译、测试等实际工作。

区分配置和执行是 Gradle 新手最容易出错的地方。任务配置代码在配置阶段就运行,而 doFirst/doLast 中的动作代码只在执行阶段运行。因此,避免在任务配置时执行重操作。

4. 插件(Plugin)—— 可复用能力的封装

插件是 Gradle 扩展机制的核心。每个插件都会为项目添加:

  • 新任务(如 classestest
  • 域对象(如 SourceSet)
  • 约定默认值(如目录布局)
  • 新的 DSL 扩展(如 application{ }

最常用的官方插件:

插件标识符 主要功能
java 添加 Java 编译、测试、打包能力
application 支持可运行的 JVM 应用及 run 任务
java-library java 基础上增加 api 依赖配置
maven-publish 发布构件到 Maven 仓库

应用插件只需在构建脚本的 plugins 块中声明:

plugins {
    id("java")
    id("org.springframework.boot") version "3.0.5"
}

5. 依赖管理

Gradle 采用 变体感知 的依赖管理模型,通过配置(Configuration)来控制依赖的范围和用途。

5.1 常用依赖配置

  • implementation:依赖只在本模块内部使用,不会传递泄露给消费者(编译和运行时可见)。
  • api:依赖会泄露给消费者编译路径,适用于库模块(需 java-library 插件)。
  • runtimeOnly:仅在运行时需要,不参与编译。
  • testImplementation / testRuntimeOnly:仅用于测试源码。

5.2 声明仓库与依赖

repositories {
    mavenCentral()
    google()
}

dependencies {
    implementation("org.apache.commons:commons-lang3:3.12.0")
    testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
}

Gradle 会将声明的依赖从仓库下载到本地缓存,并在配置阶段构建依赖解析图。动态版本(如 1.+)和递增版本号的使用需谨慎,它们会影响构建的可复现性。

6. 多项目构建与 Settings 文件

任何 Gradle 构建的根目录都必须包含 settings.gradle(.kts) 文件,它用于定义项目名称和包含的子项目:

rootProject.name = "my-app"
include("core", "app")

子项目之间可以通过项目路径互相引用依赖:

// app/build.gradle.kts
dependencies {
    implementation(project(":core"))
}

Gradle 会根据 settings 文件形成项目树,在配置阶段遍历所有子项目,从而实现集中管理与跨项目任务调用。

7. 增量构建与缓存

Gradle 通过增量构建大幅提升效率:

  • 输入/输出快照:任务声明其输入和输出属性,Gradle 在连续执行时对比它们。若输入和输出自上次运行后均无变化,任务被标记为 UP-TO-DATE 并跳过。
  • 构建缓存:本地和远程缓存可以存储任务输出,使得不同机器或分支间复用,极大加速 CI/CD 构建。

要使任务支持增量,应显式注释输入输出文件/属性,例如:

abstract class MyTask : DefaultTask() {
    @get:InputFile
    abstract val sourceFile: RegularFileProperty

    @get:OutputFile
    abstract val outputFile: RegularFileProperty

    @TaskAction
    fun process() { ... }
}