Project隔离是Gradle 6.0+的渐进式安全机制,强制显式声明跨模块依赖,禁止隐式访问dependencies、tasks等;需在gradle.properties中设org.gradle.project.isolation=true(值必须为字符串"true"),并满足Gradle≥6.8、禁用废弃预览特性、使用plugins{}块等条件。

Gradle 多模块项目启用项目隔离(Project Isolation)不是“开个开关就完事”,而是 Gradle 6.0+ 引入的渐进式构建安全机制,核心目标是阻止跨模块隐式依赖、强制显式声明、提前暴露配置错误。它默认关闭,必须手动启用,且一旦开启,会立刻报错——不是因为写错了,而是因为原来“能跑”的写法其实不合规。
什么是 project isolation,它拦住哪些写法
Project isolation 要求:一个模块(project(':foo'))在被其他模块依赖时,它的 build.gradle 中定义的任何 dependencies、configurations、tasks 都不能被依赖方直接访问或隐式继承。换句话说,你不能再靠“父项目里写了 implementation 'x',子模块就自动有 x”这种路径偷懒。
典型被拦住的行为包括:
- 根项目的
subprojects { dependencies { implementation '...' } }向所有子模块注入依赖(隔离后子模块看不到这个块) - 在
settings.gradle里用includeBuild引入外部构建,但没声明dependencyResolutionManagement的 repository - 某个模块的
build.gradle里直接调用另一个模块的tasks.named('jar')或读取其project.version - 通过
gradle.rootProject或gradle.allprojects动态遍历并修改其他模块配置
gradle.properties 里怎么配才真正生效
只加 org.gradle.configuration-cache=true 不够,项目隔离由另一个独立开关控制:
在 gradle.properties 中必须显式设置:org.gradle.project.isolation=true。注意这不是布尔值开关的简写——Gradle 6.x/7.x 实际认的是字符串值 true,写成 org.gradle.project.isolation=on 或 =enabled 都无效。
同时要确保:
- Gradle 版本 ≥ 6.8(6.0 初版支持但问题多,6.8 是第一个稳定可用的版本)
- 没有在
settings.gradle中使用已废弃的enableFeaturePreview('VERSION_CATALOGS')冲突配置 - 所有模块的
build.gradle使用的是plugins { id '...'}块,而非旧式apply plugin: '...'(后者在隔离模式下无法解析插件类路径)
启用后第一波报错怎么修
启用后最常见报错是:Could not resolve all files for configuration ':module-a:compileClasspath'. Cannot query value from provider,本质是某个模块试图从另一个模块的 configurations.apiElements 或 outgoing.artifacts 拿东西,但隔离后这些 provider 被封掉了。
修复原则就一条:把“跨模块读取”转为“跨模块声明”。例如:
- 原写法:
project(':common').configurations.apiElements.outgoing.artifacts.singleFile→ 改为在:common的build.gradle里用publishing { publications { mavenJava(MavenPublication) { from components.java } } }显式发布,再让依赖方用implementation 'group:common:1.0'坐标引用 - 原写法:
rootProject.ext.version = '1.2.3'+ 子模块读rootProject.ext.version→ 改为统一用versionCatalogs或gradle.properties定义libs.versions.core - 原写法:
subprojects { tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } }→ 改为每个模块单独配置,或提取成公共插件,在buildSrc里封装逻辑
为什么 buildSrc 里的代码突然不 work 了
项目隔离会限制 buildSrc 对主项目中 Project 实例的访问粒度。比如你在 buildSrc/src/main/groovy/MyPlugin.groovy 里写了 project.subprojects.each { it.plugins.apply('java') },隔离后会抛 IllegalStateException: Project isolation prevents access to subprojects。
正确做法是:把这类逻辑下沉到 settings.gradle 的 pluginManagement 或 dependencyResolutionManagement 块中,或者改用 precompiled script plugins(即 buildSrc/src/main/kotlin/my-conventions.gradle.kts),让 Gradle 在配置阶段前就完成插件注册,避开运行时跨项目反射。
真正的难点不在配置开关,而在于你得承认:过去那些“省事但模糊”的模块间耦合,现在必须一刀切掉——不是 Gradle 变苛刻了,是你项目的隐性依赖终于浮出水面了。











