`
白黑山河
  • 浏览: 47317 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
文章分类
社区版块
存档分类
最新评论
阅读更多

本文记录groovy dsl相关的内容,通过对语法层面的探索,描述实际中如何应用

文档结构:

  1. 讨论groovy利于dsl的语言特性,以及如何利用它们
  2. 对于其中一些特性,详细解说细节部分和需要注意的地方
  3. 讨论一下常用的dsl模式

 

groovy利于dsl的语言特性:

dsl的易用性取决于其语法结构是否贴近domain。groovy的动态特性有利于定义关键字和书写结构,而语法特性则能让语法更加贴近直观自然的表达方式。

动态特性

  • 闭包,可以改变其delegate。这种改变闭包执行的上下文,从而访问存在于其他上下文中的变量和方法的做法,是构建dsl的非常重要的手段
// builder模式构建xml
xml = new BuilderSupport()
xml.root {
    person {
        name("白山黑水")
        site("baishanheishui.iteye.com")
    }
}
        
        以上例子展示了‘改变闭包上下文’可以带来的效果,由于闭包的上下文即delegate被替换成了xml,所以闭包中所有出现的字面量最终都被调用成xml.invokeMethod(name, args),在这个方法中统一调用了build方法:createNode(nodeName).关于这点更详细的参考见后面。
  • 脚本的value binding
// 更彻底的dsl,仅作示例, 不会真这么用
// example.groovy
root {
    person {
        name("白山黑水")
        site("baishanheishui.iteye.com")
    }
}

// useExample.groovy
def xml = new File('example.groovy').text
builder = new MarkupBuilder()
def shell = new GroovyShell(binding)
xmlContent = ""
shell.evaluate("xmlContent = builder.$xml") // 通过value binding实现
println xmlContent.toString()

         如何灵活应用好双向传值是关键。更详细的参考见后面 
  • 动态方法:
    • invokeMethod和methodMissing支持调用不存在的方法
    • 通过metaClass动态增加方法的机制
    • expando方式的动态构建对象的机制
    • use(Category)机制
      • 作用是,1.给对象增加领域方法,表达更直观,比如著名的1.day;2.形成方法链,方法链也是静态语言常用的一种dsl构建模式;3.和metaClass相比,无侵入性
语法特性
  • 更自然的表达:
    • 命名参数,方法调用时,可以通过指定实参对应的形参名称达到随意安排实参传递顺序的目的,同时groovy会对方法声明中未出现的形参名称进行动态的归类成hashmap,作为第一个参数传入
    • getter,setter和getProperties语法糖
    • 操作符重载,如plus,leftShift,可重载操作符列表点此
    • 闭包
    • asType
  • 省略:
    • 闭包,闭包为方法唯一参数时,方法调用可以省略括号
    • 方法有一个以上参数时,单独的方法调用时可以省略括号
    • 脚本中可以省略声明变量的类型,包括关键字def(原因其实是脚本中有一个隐含的binding对象)
类库支持:
  • builder库提供了树形结构数据构建的dsl支持,可以直接应用构建如xml这样的文档,也可以方便的进行扩展
关于语言特性的一些详细解说:
  • expando:expando可以简单理解为一种map。由于在groovy中函数(闭包)可以作为值来传递,并且properties的读写可以直接以.key来完成,因此expando和map都能动态的增加field和method.唯一不同的是,expando非常的纯粹,可以理解为没有自带方法的一种map.比较遗憾的是map和expando都没有属于自己的this
// map
def map = [:]
map.printId = {-> map.id}
map.id = 1
map.toString = {println 'overrided toString'}

map.printId() // 1
map.toString() // 没有输出,toString没有被override

// expando
def expando = new Expando()
expando.keys = {'keys'} // 没有map的那些方法
expando.toString = {'overrided toString'} // 甚至toString也可以自由覆盖
println expando.toString() // overrided toStirng
  •   闭包的上下文解析 delegate, owner, this:
  • value binding:所有脚本有一个隐含的Binding对象,可以认为是一个属性对象。相比闭包的delegate替换,value binding使用和功能都较为简单
// useBind.groovy
noDeclare = 'do not need to declare'
println binding.noDeclare
println noDeclare
// useBindCommunicate.groovy
def scriptBinding = new Binding()
def shell = new GroovyShell(scriptBinding) // init
shell.evaluate('useBind.groovy')
println scriptBinding.noDeclare // useBind脚本中的值传递出来了,反之亦然



 
dsl 模式掠影:
  • 方法链
    • 将一系列方法从左往右连缀起来调用,通过使用有意义的方法名,使得代码符合domain语义
    • 方法返回领域对象,从而可以进行连续调用
    • 通过对非领域对象注入'返回领域对象‘的方法,从而开启方法链
    • groovy常常使用use,metaClass方式进行方法注入
1/**Integer**/.days/**Duration**/.ago/**Date**/


use(FileHelper) {"example".file.split(SIZE).writeFiles(POSTFIX)}
 
  • 声明序列,功能序列
    • 使用声明风格的代码,逐行书写,每行语句执行一个功能
    • 每个方法都是一个'命令’,状态通过内部传递,从而使每一行的语句功能单一,形式简单
    • 为了去除声明中的冗余内容,groovy中可以使用closure,binding等方式简化声明的书写
config {
    setName(name)
    setPassword(pwd)
}

testOr {
    between(value, upper, lower)
    max(array, expectedMax)
}
 
  • 独立文件的
    • 在一个独立文件中书写dsl,从解释程序中读入dsl文件并执行。这个是最纯粹的方式
    • 作为一个embedding dsl,它总是遵循宿主语言的语法规则,因此为了使dsl更具有domain语义,需要预先定义关键字和关键方法,以供dsl中直接调用
    • groovy中使用groovyScriptEngine和groovyShell分析和调用dsl文件
// app.groovy
get ("/index") {
    render "index.vm"
}

get ("/json/status") {
    def pid = params['pid']
    def pInfo = UserStatus.find(pid)
    render "status.vm", {"pInfo": pInfo}
}

 
  • builder
    • groovy中提供了builder库,可以直接进行扩展.由于这个库直接提供了dsl风格的builder指令,因此只要继承实现具体的build方法,就可以完成一个基于builder模式的dsl
// xml build
xml.user(name:uname, id: uid) {
}
 
分享到:
评论

相关推荐

    Groovy DSL 动态规则(rule)执行引擎流程引擎特色风控系统规则引擎动态接口配置(低代码)

    自创Groovy DSL 动态规则(rule)执行引擎, 流程引擎. 特色 风控系统, 规则引擎, 动态接口配置(低代码)Groovy DSL 动态规则(rule)执行引擎。DSL(特定领域语言): 开发 和 业务 共识的语言。方便业务表达需求, 方便开发...

    Groovy DSL

    ### Groovy DSL:基于领域的特定语言开发指南 #### Groovy简介 Groovy是一种基于Java平台的灵活、强大的脚本语言,它与Java高度兼容,能够直接调用Java库中的类和方法,反之亦然。这种无缝集成使得Groovy成为一种极...

    Groovy DSL 动态规则(rule)执行引擎

    Groovy DSL动态规则执行引擎是一种基于Groovy语言的领域特定语言(Domain-Specific Language)来构建规则引擎的解决方案。这种引擎特别适用于流程控制、风险管理系统以及动态接口配置,特别是那些需要快速迭代和低...

    用Groovy实现DSL领域定义语言

    在groovy中实现DSL领域特定语言的技术。 版权声明: 本系列文章是从原著《Groovy For Domain-Specific Languages》(原作者: Fergal Dearle)中翻译而来,从中加入了一些本人自己的读书笔记和理解。本系列文章不为...

    groovy 一个不错的文档 实现dsl

    ### Groovy实现领域特定语言(DSL)的知识点详解 #### 标题与描述解析 - **标题**: "groovy 一个不错的文档 实现dsl" - **描述**: "groovy 一个不错的文档 实现dsl" 标题与描述均指向了一个关于如何使用Groovy语言...

    groovy-dsl:创建Groovy DSL

    Groovy DSL,全称为Groovy Domain-Specific Language,是一种利用Groovy编程语言构建的特定领域语言。DSL旨在为特定的应用场景或领域提供简洁、直观的语法,使得非程序员或者领域专家也能更容易地理解和操作。Groovy...

    groovy-ssh, 在 Groovy DSL上,基于SSH自动化工具.zip

    groovy-ssh, 在 Groovy DSL上,基于SSH自动化工具 Groovy SSH是基于DSL的自动化工具,提供远程命令执行和文件传输。https://gradle-ssh-plugin.github.io捐赠这是一个在Apache许可以版 2.0下许可以的开源软件。 欢迎...

    groovy-docker-dsl:Docker 的 Groovy DSL(想想 Fig 的健康检查和更改容器的重启)

    Groovy Docker DSL 使用 Groovy DSL 思考 ,您可以实现钩子、健康检查和监视包含 Dockerfile 的文件夹以进行更改,并根据需要自动重新构建和重新启动容器。 动机: Fig 很棒,但我需要一些可以让我做一些事情的...

    infra-dsl:用于基础架构的Groovy DSL

    红外DSL 用于Terraform的Groovy DSL。 干净,简单的方法来定义代码中的基础结构。不久将有更多描述。 享受下面的示例:) java -jar infra-dsl-VERSION.jar path_to_your_file.groovy Infrastructure . resource...

    Android-从Groovy转换为KotlinDSLforGradle专注于Android

    Groovy是早期Gradle构建系统的主要语言,而Kotlin DSL(Domain Specific Language)则是近年来逐渐流行的趋势,特别是在Android开发中。Kotlin DSL提供了更简洁、类型安全的构建脚本,提升了开发效率和代码可读性。 ...

    vertx-web-groovy-dsl:简单的Groovy DSL声明Vert.x Apex路由

    vertx-web-groovy-dsl Groovy DSL声明Vert.x Web路由 如果您使用Groovy,则本项目旨在提供另一种方法来使用vert-web定义网络路由,这种方式更具Groovy风格。 最有趣的功能是能够使用嵌套闭包以嵌套方式声明路由器...

    groovy-dsl-talk:关于在Groovy中创建DSL的闪电演讲

    Groovy DSL 关于利用Groovy支持特定领域语言的闪电演讲 资源 演示幻灯片: :

    Groovy.for.Domain.Specific.Languages.pdf

    该书深入浅出地介绍了Groovy在DSL设计与实现中的独特优势,为读者提供了丰富的实践指导和理论基础。 ### Groovy与领域特定语言 #### 1. Groovy概述 Groovy是一种灵活、强大的脚本语言,它运行在Java平台上,能够...

    groovy-jmx-dsl:用于基于 Swing 的 JMX 仪表板的 Groovy DSL

    Groovy-JMX-DSL 是一个专门用于构建基于 Swing 的 JMX (Java Management Extensions) 仪表板的 Domain-Specific Language(领域特定语言)。这个项目利用了 Groovy 的灵活性和表达力,使得开发者能够更加便捷地创建...

    最新 groovy开发包

    通过Groovy DSL(Domain Specific Language),你可以定制构建过程,实现复杂的依赖管理和自动化任务。 5. **Spock测试框架**:Groovy还有一个流行的测试框架——Spock,它提供了一种声明式的、行为驱动的测试风格...

    Programming_Groovy_2.7z

    - Gradle的Groovy DSL(领域特定语言)比Ant或Maven的XML配置更易读、易写。 6. **Spock测试框架** - Groovy还催生了Spock测试框架,它提供了一种声明式的测试语法,使测试代码更具可读性和维护性。 7. **Groovy...

    Android-缺少GradleKotlinDSL的迁移指南

    然而,有些开发者可能还在使用传统的Groovy DSL,面临向Kotlin DSL迁移的问题。这篇指南将详细解释如何进行这种迁移,帮助你充分利用Kotlin DSL的优势。 一、Gradle Kotlin DSL的优势 1. 更强的类型安全:Kotlin是...

    job-dsl-plugin:Jenkins Jobs的Groovy DSL-Sweeeeet!

    Jenkins的“作业DSL /插件”由两部分组成:允许用户使用基于groovy的语言描述作业的领域特定语言(DSL),以及管理脚本和Jenkins更新的Jenkins插件。结果是创建和维护的作业。 不推荐使用 该项目已移至 。 此存储库...

Global site tag (gtag.js) - Google Analytics