应使用 Gradle 的 pluginManagement + dependencyManagement 两级控制:通过 gradle/libs.versions.toml 统一管理版本、bundles 和 libraries,并在 settings.gradle 中配置 pluginManagement 和 enableFeaturePreview('typesafe-project-accessors');子模块仅声明插件 ID,不写版本;统一构建逻辑用 subprojects(非 allprojects);测试依赖通过 plugins.withId('java') 条件引入。

重复的 plugins 和 dependencies 怎么统一声明
多模块项目里每个 build.gradle 都写一遍 id 'java'、id 'org.springframework.boot' version '3.3.0',不仅冗余,升级时还容易漏改。正确做法是用 Gradle 的 pluginManagement + dependencyManagement 两级控制。
在根目录 settings.gradle 同级建 gradle/libs.versions.toml(推荐),或用 gradle.properties 管理版本;再在 settings.gradle 里通过 pluginManagement 声明插件版本和应用范围:
pluginManagement {
plugins {
id('java') version '17.0.2'
id('org.springframework.boot') version '3.3.0'
}
resolutionStrategy {
eachPlugin {
if (requested.id.namespace == 'org.springframework.boot') {
useModule('org.springframework.boot:spring-boot-gradle-plugin:${requested.version}')
}
}
}
}
子模块只需写 plugins { id 'org.springframework.boot' },不用带 version,版本由根配置兜底。
allprojects 和 subprojects 该选哪个
allprojects 会作用于根项目本身(即 rootProject),而根项目通常不参与编译,只做协调。如果在里面加 apply plugin: 'java' 或配置 sourceCompatibility,会导致根项目尝试编译源码,报 Could not resolve all files for configuration ':compileClasspath' 这类错误。
所以统一构建逻辑一律用 subprojects:
subprojects {
apply plugin: 'java'
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
repositories {
mavenCentral()
}
}
-
allprojects只适合放repositories全局源(但更推荐放在pluginManagement或settings.gradle的dependencyResolutionManagement) -
subprojects是实际配置 Java 编译、依赖、测试等行为的唯一安全位置 - 若某个模块(如
infrastructure)需要额外依赖,单独在它自己的build.gradle里追加implementation即可,不破坏统一性
怎么让不同模块复用相同的 testImplementation 依赖
像 junit-jupiter、mockito-core、assertj 这类测试依赖,90% 模块都用得上,但直接写死在 subprojects 里会污染非测试模块(比如纯 data model 模块可能不需要 JUnit)。
解决方案是用 withPlugin 条件加载:
subprojects {
plugins.withId('java') {
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2'
testImplementation 'org.mockito:mockito-core:5.12.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.2'
}
tasks.test {
useJUnitPlatform()
}
}
}
这样只有真正应用了 java 插件的模块才会引入测试依赖,避免误配。
gradle/libs.versions.toml 里怎么定义多层级别依赖
单靠 versions 表不能表达 “Spring Boot BOM 控制所有 starter 版本” 这种语义。必须用 bundles + libraries + versions 三层配合:
[versions]
springBoot = "3.3.0"
junit = "5.10.2"
[libraries]
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web" }
[bundles]
spring-boot-dependencies = ["spring-boot-starter-web", "spring-boot-starter-data-jpa"]
子模块中就能简洁引用:
dependencies {
implementation libs.bundles.`spring-boot-dependencies`
testImplementation libs.junit.jupiter
}
注意:libs.bundles.xxx 是 Gradle 自动展开的,不是字符串拼接;反引号仅在 bundle 名含连字符时必需。
最容易被忽略的是:libs.versions.toml 不会自动生效,必须在 settings.gradle 显式启用:
enableFeaturePreview('typesafe-project-accessors')
否则 libs 命名空间根本不存在,会报 Could not get unknown property 'libs'。











