繁体   English   中英

构建 java 项目时 build.gradle 中的 Groovy 语法

[英]Groovy syntax in build.gradle when build java project

我在 build.gradle 中定义了一个任务,如下所示:

task copyConfig(type: Copy) {
    from ""
    into ""
}

在我看来, taskproject中的一种方法,它将整个其余部分作为参数,
copyConfig也是一个有两个参数的方法: [type:copy]和一个闭包

{
    from ""
    into ""
}

但我想知道copyConfig是自定义的,没有这样的方法名为copyConfig
那么为什么它有效? 究竟发生了什么。

这是等效的java

Action<Copy> action = task -> {
   task.from("xxx");
   task.into("yyy");
}; 
project.getTasks().create("copyConfig", Copy.class, action);

build.gradle 不是纯粹的 groovy,而是它的扩展。 gradle 有一个解释阶段,将适应任务定义

task copyConfig(type: Copy) {
    from ""
    into ""
}

Task task(Map<String, ?> args, String name, Closure configureClosure);


还有一些与此相关的其他 QA:
了解 gradle 任务定义中的 groovy 语法
build.gradle 中的 gradle 任务方法语法
groovy 语言中的 gradle 任务定义是什么?

Gradle 只是充分利用 Groovy 提供的功能来创建不错的 DSL。

不管 Gradle 是怎么做的(其他答案已经指出),我们都可以使用基本的 Groovy DSL 创建工具自己轻松实现。

例如,以下代码演示了我们如何使用基类评估脚本(如 Gradle 文件),这意味着脚本运行时就好像它在我们选择的类(在本例中为MyScript )中一样:

import org.codehaus.groovy.control.CompilerConfiguration

class Main {
    static void main( args ) {
        def compilerConfig = new CompilerConfiguration()
        compilerConfig.scriptBaseClass = 'MyScript'
        def shell = new GroovyShell( this.class.classLoader, compilerConfig )

        shell.evaluate( '''
    task helloWorld {
        println "Hello world"
    }
    ''' )
    }
}

abstract class MyScript extends Script {
    def task( taskObject ) {
    }
}

当我们评估这个脚本时:

task helloWorld {
    println "Hello world"
}

首先,通过使用 Groovy 语言语法规则,我们可以将其转换为更像 Java 的语法以了解它将做什么:

task(helloWorld(() -> {
    System.out.println("Hello world");
}));

因此, task()方法调用应该可以工作,因为我们在脚本的基类中定义了一个方法: def task( taskObject ) ...

但是没有helloWorld方法,所以这应该会失败,猜猜当你运行它时会发生什么?

groovy.lang.MissingMethodException: 
No signature of method: Script1.helloWorld() is applicable for argument types: (Script1$_run_closure1)...

我们可以看到我们对上面的 Groovy 语法的解释是正确的:Groovy 调用了helloWorld和一个Closure的实例!

现在,我们可以做一些聪明的事情来允许创建任何名称的任务......像这样:

abstract class MyScript extends Script {
    def currentTaskName

    def task( taskObject ) {
        println "Trying to create task $taskObject"
    }

    def methodMissing( String name, def args ) {
        [ name: name, config: args ]
    }
}

methodMissing 是另一个 Groovy 特性,它允许您处理对实际上不存在的类的任何方法的调用!

猜猜这打印了什么!

Trying to create task [name:helloWorld, config:[Script1$_run_closure1@70325e14]]

这就是它的全部……Gradle 可能会做一些更高级的魔法,比如改变已编译的 Groovy 源代码的 AST(任何人都可以在 Groovy 中做),但本质上,就是这样。

如何使用配置闭包来配置任务留给读者作为练习:P

如果您想了解更多信息,请查看Groovy DSL 文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM