4. 根build.gradle与子build.gradle的职责划分

4.1 职责划分原理

在Gradle多模块项目中,根build.gradle和子build.gradle各自承担不同的配置责任。合理的职责划分可以消除重复、降低维护成本、统一构建环境,同时允许子模块保留必要的定制能力。

  • 根build.gradle:定义全局属性、公共仓库、公共插件版本(通过 plugins 块声明但不 apply)、所有项目或子项目共享的配置(如 allprojects 和 subprojects 块)。
  • 子build.gradle:仅声明本模块特有的依赖、任务、插件应用、源集配置等,避免重复根级配置。

4.2 allprojects 与 subprojects 块

块作用域典型用途
allprojects根项目 + 所有子项目仓库配置、公共插件版本、全局属性
subprojects仅所有子项目(不含根)子类项目通用配置(如 Java 插件、编码、JUnit 版本)
⚠️ 常见错误:不要将子模块特有的依赖声明放在 subprojects 块中,否则所有子模块都会获得该依赖(即使不需要)。应把公共依赖(如日志门面)放 subprojects,私有依赖放子 build.gradle。

4.3 插件声明位置

Gradle 推荐在根 build.gradle 中使用 plugins 块统一管理插件版本,子模块再通过 plugins 块或 apply 选择性应用。

// 根 build.gradle —— 只声明版本,不 apply
plugins {
    id 'org.springframework.boot' version '3.2.1' apply false
    id 'java' apply false   // Java 插件也以版本方式管理
}

subprojects {
    // 子模块公共配置
    apply plugin: 'java'
}

子模块只需引用插件 ID(无需版本):

// 子模块 build.gradle(如 service/build.gradle)
plugins {
    id 'org.springframework.boot'
    id 'java'
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
}

4.4 实现流程:典型多模块布局

  1. 创建根项目:在 settings.gradle 中声明所有子模块名称。
  2. 编写根 build.gradle:配置 allprojects 块统一仓库,subprojects 块设置通用插件和编译选项。
  3. 编写子 build.gradle:每个子模块声明自己的依赖、任务和自定义配置。
  4. 验证配置:运行 gradle projects 查看项目层次,运行 gradle properties 检查继承的属性值。

4.5 职责划分架构图

根与子 build.gradle 职责划分 根 build.gradle 全局职责 • plugins 声明版本(不 apply) • allprojects 块:仓库 • subprojects 块:公共配置 • 项目 level 属性 子模块 A 子模块 B 子模块 C 子模块 D 本模块职责 • 私有依赖声明 • 特定任务定义 • 插件 apply(版本继承自根) 本模块职责 • 私有依赖声明 • 特定任务定义 • 插件 apply(版本继承自根) 关键原则:在根级细粒度控制继承范围 • allprojects 用于所有项目(包括根)的全局配置(如仓库) • subprojects 仅影响子模块(如图中 A/B/C/D),根项目不受影响 settings.gradle include(':A',':B',':C',':D') 模块注册

4.6 调试技巧

  • 使用 gradle properties 查看当前项目所有属性,区分哪些来自根 build.gradle 的 allprojects 块。
  • 使用 gradle projects 检查 project 树是否正确。
  • 添加 logger.quiet("root: ${project.rootDir}") 到根 build.gradle 验证执行顺序。
💡 最佳实践:将 plugins 版本声明放在根 build.gradle 的 plugins 块内,并设置 apply false。这样子模块直接引用插件名即可,保证版本一致性同时避免重复。

4.7 常见错误与解决方案

错误场景原因解决方案
子模块找不到插件根插件版本声明未加 apply false,且子模块未主动 apply确保根只用 apply false,子模块显式调用 plugins { id '...' }
全局属性被子模块覆盖子 build.gradle 中使用了同名属性使用 ext 命名空间(如 ext.libVersion = '1.0')并在子模块通过 rootProject.ext 引用
所有子模块都应用了无关依赖在 subprojects 块中声明了模块私有依赖只将真正共用的依赖放入 subprojects 块,其他放入子 build.gradle

4.8 性能与稳定性优化

  • 避免在 allprojects 中执行耗时代码(如网络请求),因为会作用于根项目,可能造成额外延迟。
  • 善用配置避免:subprojects { afterEvaluate { ... } } 仅在子模块评估后执行,减少无用配置。
  • 插件管理集中化:所有第三方插件版本仅在根 build.gradle 的 plugins 块中定义,避免子模块版本冲突。
  • 使用 buildSrc 或版本目录(Version Catalog)管理版本号,可进一步提升一致性(第5章将详述)。