You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Gradle 7(Groovy 3)闭包内方法执行异常问题求助

修复Gradle 7升级后自定义插件闭包调用失败的问题

问题根源

  1. 错误的输入注解:@Input注解不能用于Closure类型,Gradle 7对任务输入的验证更加严格,Closure不属于Gradle认可的可序列化输入类型,会触发配置阶段提前评估闭包。
  2. 闭包委托上下文错误:Gradle 7中标记为@Input的闭包会在配置阶段被评估,此时闭包的默认委托是自定义Task实例,而filesMatching()是CopySpec的专属方法,Task实例没有该方法,因此抛出找不到方法的错误。

推荐修复方案:改用Action<CopySpec>替代Closure

Gradle官方推荐使用Action接口替代闭包进行配置,类型更安全,能彻底避免委托上下文混乱的问题。

步骤1:修改自定义插件代码

import org.gradle.api.Action
import org.gradle.api.file.CopySpec
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

class MyCustomTask extends DefaultTask {
    // 替换原Closure属性为Action<CopySpec>,默认空实现
    @Optional
    Action<CopySpec> myCopyAction = Action.nop()

    private void copyFiles() {
        println "--------------------------Copying"
        project.copy { CopySpec copySpec ->
            from "${project.projectDir}/src/main/resources"
            into "${buildDir}"
            // 将Action直接应用到CopySpec上下文
            myCopyAction.execute(copySpec)
        }
    }

    @TaskAction
    def custom() {
        // ... 原有业务逻辑
        copyFiles()
        // ... 原有业务逻辑
    }
}

步骤2:主项目调用代码(无需修改)

Groovy会自动将闭包转换为Action实例,因此主项目代码可以保持不变:

task(type: MyCustomTask, 'custom') {
    myCopyAction = {
        filesMatching('**/my.yaml') {
            filter { it.replace('${test}', 'TEST') }
        }
    }
    // ... 其他配置
}

如果希望完全保留原属性名myClosure,只需修改插件中的属性名即可,主项目代码无需调整:

@Optional
Action<CopySpec> myClosure = Action.nop()

兼容Closure的替代方案(不推荐)

如果必须保留Closure类型,需要移除@Input注解,并确保闭包仅在执行阶段评估,同时明确设置委托策略:

import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction

class MyCustomTask extends DefaultTask {
    // 移除@Input注解,避免配置阶段提前评估
    @Optional
    Closure myClosure = { }

    private void copyFiles() {
        println "--------------------------Copying"
        project.copy {
            from "${project.projectDir}/src/main/resources"
            into "${buildDir}"
            final cl = myClosure.clone()
            // 设置委托策略为优先使用CopySpec的方法
            cl.resolveStrategy = Closure.DELEGATE_FIRST
            cl.delegate = delegate
            cl()
        }
    }

    @TaskAction
    def custom() {
        // ... 原有业务逻辑
        copyFiles()
        // ... 原有业务逻辑
    }
}

这种方式虽能临时解决问题,但不符合Gradle现代API设计理念,类型不安全,后续版本仍可能出现兼容性问题,因此优先推荐Action方案。

内容的提问来源于stack exchange,提问作者MKB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 00:55:13