extensions.create("xxx", xxxextension.class) 不支持嵌套,因为 xxxextension 是普通类,gradle 不会自动将其展开为 dsl 块;嵌套需外层 extension 中用 objects.newinstance() 创建嵌套实例,且嵌套类必须 public、无参构造、属性全为 property 或 provider。

为什么 extensions.create("xxx", XxxExtension.class) 不支持嵌套?
因为 XxxExtension 类本身只是个普通 Java/Kotlin 类,Gradle 并不会自动把它“展开”成 DSL 块。你看到的 android { kotlinOptions { jvmTarget = "17" } } 这种嵌套,本质是两层 extension 实例注册:外层 android 是一个 extension,它的某个属性(比如 kotlinOptions)被声明为另一个 extension 类型,并且这个属性必须是 Provider 或直接是 extension 实例——否则闭包委托失败,报错 Could not find method kotlinOptions() for arguments []。
- 必须用
ObjectFactory.newInstance()或objects.newInstance()创建嵌套 extension 实例,不能 new 出来 - 嵌套类必须是 public、无参构造、所有属性用
Property<t></t>或Provider<t></t>声明(Gradle 8.5+ 强制要求) - 外层 extension 中该字段不能是普通
String或int,否则 DSL 闭包无法绑定到它身上
configureEach 和 configure 在嵌套 extension 中怎么选?
当你在插件 apply 方法里注册嵌套 extension 时,调用方式决定配置时机和作用域:
-
extensions.configure("myPlugin", MyPluginExtension.class, ext -> { ... }):只配置已存在的实例,适用于用户已在 build script 中写了myPlugin { ... }的场景;如果还没注册,会静默失败 -
extensions.configureEach(MyPluginExtension.class, ext -> { ... }):对所有已注册和未来注册的该类型 extension 实例生效,适合做默认值填充或统一预处理 - 真正注册嵌套结构,得靠外层 extension 内部的初始化逻辑,比如在构造函数里:
this.nested = objects.newInstance(NestedExtension.class)
Kotlin DSL 下嵌套配置不补全?检查这三处
IDE 补全失效不是 Gradle 报错,而是 Kotlin 编译器没识别出 DSL 结构。常见断点:
-
build.gradle.kts里写myPlugin { nested { ... } },但 IDE 提示Unresolved reference: nested→ 检查NestedExtension是否被@get:Internal或private修饰,必须是public open class NestedExtension - 父 extension 的
nested字段类型是NestedExtension而非Property<nestedextension></nestedextension>→ Kotlin DSL 只能代理到Property或Provider字段 - 没在插件模块的
src/main/kotlin下提供MyPluginExtensions.kt文件并声明fun Project.myPlugin(action: Action<mypluginextension>)</mypluginextension>扩展函数 → Kotlin DSL 需要显式桥接函数才能触发类型推导
嵌套 extension 的生命周期风险:别在 afterEvaluate 里读取嵌套值
嵌套配置块的执行时机早于 afterEvaluate,但如果你在 afterEvaluate 里直接访问 extension.nested.someProp.get(),可能触发 Cannot query a value before it has been set。这是因为嵌套字段的 Provider 还未完成配置绑定。
- 安全做法:用
extension.nested.someProp.getOrElse("default")或someProp.convention("default")设置默认值 - 更稳妥的是监听配置完成事件:
project.afterProject { if (it == project) extension.nested.someProp.finalizeValueIfNotAlready() - 如果必须在 task 配置阶段读取,确保该 task 的
configure发生在project.afterEvaluate之后,或改用providers.of(...)延迟求值











