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

标签 java gradle groovy

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

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

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

{
    from ""
    into ""
}

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

最佳答案

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 使用 Closure 的实例调用 helloWorld!

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

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 is another Groovy feature that lets you handle calls to any method of a class that does not actually exist!

猜猜这打印了什么!

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

这就是全部内容...Gradle 可能会做一些更高级的魔法,例如更改已编译的 Groovy 源代码的 AST(任何人都可以在 Groovy 中执行此操作),但本质上就是这样。

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

检查Groovy DSL docs如果您想了解更多信息。

关于java - 构建 java 项目时 build.gradle 中的 Groovy 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59087017/

相关文章:

java - 在java中使用多线程并行化for循环

java - 多个带有配置文件的 Spring Boot 应用程序类

date - Groovy - 将时间戳字符串转换为以毫秒为单位的纪元时间

java - 来自 pom.xml 的 Maven 解析器、Shrinkwrap

java - 在java中动态创建GUI组件

android - Jitpack:无法通过示例库解决(Android Studio)

java - Spring Boot JSF 打包为 JAR

android - 如何修复 `duplicate class com.google.firebase.components`?

jenkins - 如何使用groovy在声明性jenkins管道中填充环境变量

java - 从 Java 检查 CGLib 代理的 Groovy 类