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 对象收集起来, // 作后续处理