簡體   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