Groovy DSL

Table of Contents

1. Groovy DSL

http://docs.groovy-lang.org/docs/groovy-latest/html/documentation/#_domain_specific_languages

Groovy 适合用来定义 DSL, 例如, gradle 使用的就是就是用 groovy 定义的 DSL:

plugins {
    id 'java'
    id 'application'
}

repositories {
    jcenter()
}

dependencies {
}

sourceSets {
  main {
    java {
      exclude 'MyProcessor.java'
    }
  }
}

// Define the main class for the application
mainClassName = 'HelloAnnotation'

groovy 和 DSL 相关的几点:

  1. command chains
  2. closure
  3. closure delegation

1.1. command chain

在 groovy 的语法中

  1. foo(bar) == foo bar
  2. foo(a,b) == foo a,b
  3. foo(a).bar(b) == foo a bar b
  4. foo(a).bar() == foo a bar

1.2. closure

closure 与 java lambda 类似, 使用 {} 来定义, 例如

x={println(it)}

结合 command chain:

plugins {
    id 'java'
    id 'application'
}

// 实际是一个参数为 closure 的函数调用:

plugins (
    {
        id("java");
        id("application");
    }
)

1.3. closure delegration

closure 中的自由变量可以捕获外部的环境中的变量, 例如上面的 `id` 是自由变量, 可以捕获外部的值.

通常 closure 可以捕获定义 closure 时的环境中的变量, 例如:

def foo() {
    int x=1;
    return {a->a+x}
}

x=foo();
x(10) // 11

但 groovy 的 closure 有一个特殊的 delegration 功能, 可以指定 closure 运行时从何处捕获变量

def foo() {
    return {a->a+x}
}

class A {
    int x=100
}

a=foo()
a() // exception, No such property: x for class: groovysh_evaluate

a.delegate=new A()
a(10) // 110

1.4. gradle 与 delegration

plugins {
    id 'java'
    id 'application'
}

// 相当于一个函数调用:

plugins({
    id("java");
    id("application");
})

// plugins 函数大约是这样的:

def plugins(Closure cl) {
    def spec=new PluginsSpec()
    cl.delegate=spec
    cl()
}

// PluginsSpec 可能是这样的:

class PluginsSpec {

    def id (String name) {
        ...
    }
}

// 所以 plugins 函数执行完后所有的数据会被 PluginsSpec 对象收集起来,
// 作后续处理

Author: [email protected]
Date: 2019-08-01 Thu 00:00
Last updated: 2024-02-01 Thu 14:04

知识共享许可协议