您好,登錄后才能下訂單哦!
Groovy中怎么構建DSL,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
官方定義是“Groovy中的閉包是一個開放,匿名的代碼塊,可以接受參數,返回值并分配給變量”
簡而言之,他說一個匿名的代碼塊,可以接受參數,有返回值。在DSL中,一個DSL腳本就是一個閉包。
比如:
//執行一句話 { printf 'Hello World' } //閉包有默認參數it,且不用申明 { println it } //閉包有默認參數it,申明了也無所謂 { it -> println it } // name是自定義的參數名 { name -> println name } //多個參數的閉包 { String x, int y -> println "hey ${x} the value is ${y}" }
每定義的閉包是一個Closure對象,我們可以把一個閉包賦值給一個變量,然后調用變量執行
//閉包賦值 def closure = { printf("hello") } //調用 closure()
當調用的方法需要參數時,Groovy 不要求使用括號,若有多個參數,那么參數之間依然使用逗號分隔;如果不需要參數,那么方法的調用必須顯示的使用括號。
def add(number) { 1 + number } //DSL調用 def res = add 1 println res
也支持級聯調用方式,舉例來說,a b c d
實際上就等同于 a(b).c(d)
//定義 total = 0 def a(number) { total += number return this } def b(number) { total *= number return this } //dsl a 2 b 3 println total
我們結合 Groovy 中對屬性的訪問就是對 getXXX 的訪問,將無參數的方法名改成 getXXX 的形式,即可實現“調用無參數的方法不需要括號”的語法!比如:
def getTotal() { println "Total" } //DSL調用 total
MOP:元對象協議。由 Groovy 語言中的一種協議。該協議的出現為元編程提供了優雅的解決方案。而 MOP 機制的核心就是 MetaClass。
有點類似于 Java 中的反射,但是在使用上卻比 Java 中的反射簡單的多。
常用的方法有:
invokeMethod()
setProperty()
hasProperty()
methodMissing()
以下是一個methodMissing的例子:
detailInfo = [:] def methodMissing(String name, args) { detailInfo[name] = args } def introduce(closure) { closure.delegate = this closure() detailInfo.each { key, value -> println "My $key is $value" } } introduce { name "zx" age 18 }
@BaseScript
需要在注釋在自定義的腳本類型變量上,來指定當前腳本屬于哪個Delegate,從而執行相應的腳本命令,也使IDE有自動提示的功能:
腳本定義 abstract class DslDelegate extends Script { def setName(String name){ println name } }
腳本:
import dsl.groovy.SetNameDelegate import groovy.transform.BaseScript @BaseScript DslDelegate _ setName("name")
使用以上介紹的方法,只能在腳本里執行單個命令,如果想在腳本里執行復雜的嵌套關系,比如Gradle中的dependencies,就需要@DelegatesTo支持了,@DelegatesTo執行了腳本里定義的閉包用那個類來解析。
上面提到一個DSL腳本就是一個閉包,這里的DelegatesTo其實定義的是閉包里面的二級閉包的格式,當然如果你樂意,可以無限嵌套定義。
//定義二級閉包格式 class Conf{ String name int age Conf name(String name) { this.name = name return this } Conf age(int age) { this.age = age return this } } //定義一級閉包格式,即腳本的格式 String user(@DelegatesTo(Conf.class) Closure<Conf> closure) { Conf conf = new Conf() DefaultGroovyMethods.with(conf, closure) println "my name is ${conf.name} my age is ${conf.age}" } //dsl腳本 user{ name "tom" age 12 }
腳本可以在IDE里直接執行,大多數情況下DSL腳本都是以文本的形式存在數據庫或配置中,這時候就需要先加載腳本再執行,加載腳本可以通過以下方式:
CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); compilerConfiguration.setScriptBaseClass(DslDelegate.class.getName()); GroovyShell shell = new GroovyShell(GroovyScriptRunner.class.getClassLoader()); Script script = shell.parse(file);
給腳本傳參數,并得到返回結果:
Binding binding = new Binding(); binding.setProperty("key", anyValue); Object res = InvokerHelper.createScript(script.getClass(), binding).run()
關于Groovy中怎么構建DSL問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。