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 相关的几点:
- command chains
- closure
- closure delegation
1.1. command chain
在 groovy 的语法中
- foo(bar) == foo bar
- foo(a,b) == foo a,b
- foo(a).bar(b) == foo a bar b
- 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 对象收集起来,
// 作后续处理
