应优先使用 subprojects 替代 allprojects,因其仅作用于子模块而避开根项目,避免配置污染;仓库和插件版本应移至 settings.gradle 的 dependencyResolutionManagement 和 pluginManagement 块;复杂项目宜采用 convention plugins 实现显式、可维护的配置复用。

allprojects 为什么容易被滥用
很多人把 allprojects 当成“全局配置保险柜”,一写依赖仓库、插件版本、JVM参数就往里塞。但它实际作用是:对当前 Project 及其所有子 Project 执行一次闭包。根项目(root project)本身也被包含在内,而它通常不需要编译逻辑、不需要 Android 插件、甚至不该参与某些任务执行——结果就是构建变慢、插件冲突、gradle sync 失败,或者子模块莫名其妙继承了不该有的配置。
用 subprojects 替代 allprojects 是最直接的解法
subprojects 只作用于所有子模块,完全绕过 root project,天然规避“根项目被污染”的问题。尤其在 Spring Boot 多模块或 Android 库模块聚合场景下,这是更安全的默认选择。
-
subprojects不会触达根项目的build.gradle,所以你可以在根项目里自由写插件管理、版本目录定义等纯构建基础设施代码 - 如果某个子模块需要例外处理(比如一个纯 Kotlin 工具模块不应用 Java 插件),可以后续单独调用
configure(project) { ... }覆盖 - Android 项目中,
subprojects配合plugins { id("com.android.library") apply false }更可控,避免 application 模块被错误地当作 library 处理
真正该放哪里?看配置项的语义归属
不是所有“看起来通用”的配置都适合放进 subprojects。关键判断标准是:这个配置是否属于“每个模块的构建行为”,还是“整个构建过程的策略”。
- 仓库地址(
repositories)→ 放dependencyResolutionManagement块里(在settings.gradle中),这才是 Gradle 5.6+ 推荐的统一位置,比写在subprojects里更早生效、更可靠 - 插件版本约束(如
id("org.springframework.boot") version "3.3.4")→ 放pluginManagement块(也在settings.gradle),避免子模块各自声明导致版本不一致 - Java 编译选项(
java { sourceCompatibility = JavaVersion.VERSION_17 })→ 放subprojects或更细粒度的withPlugin("java")条件块里,因为这是每个模块自己的事
复杂项目建议彻底弃用 allprojects/subprojects,改用 convention plugins
当模块类型开始分化(比如有 Spring Boot 启动模块、纯 domain 模块、Gradle Plugin 模块、Kotlin Multiplatform 模块),靠 subprojects 统一配置就会越来越别扭。这时候应该把共性逻辑抽成独立的 convention plugin,例如:
plugins {
id("com.example.java-library-conventions") version "1.0"
}
然后在每个子模块的 build.gradle 里显式声明,而不是隐式继承。这样:
- 模块职责清晰,谁用了什么约定一目了然
- IDE 导航和重构更准确(
subprojects里的闭包 IDE 很难跳转) - 构建扫描(
./gradlew --scan)能明确看到每个模块加载了哪些插件,便于排查性能瓶颈
真正难的不是怎么写配置,而是判断哪部分该由构建系统统一兜底,哪部分该由模块自己声明。越晚做这个区分,后期拆分或迁移成本越高。











