<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用Groovy構建DSL

          共 3268字,需瀏覽 7分鐘

           ·

          2021-03-07 11:52

          DSL(Domain Specific Language)官方定義為:針對某一領域,具有受限表達性的一種計算機程序設計語言

          常用于聚焦指定的領域或問題,這就要求 DSL 具備強大的表現(xiàn)力,同時在使用起來要簡單。由于其使用簡單的特性,DSL 通常不會像 Java,C++等語言將其應用于一般性的編程任務。

          對于 Groovy 來說,一個偉大的 DSL 產(chǎn)物就是新一代構建工具——Gradle,接下來讓我們看下有哪些特性來支撐Groovy方便的編寫DSL:

          一、原理

          1、閉包

          官方定義是“Groovy中的閉包是一個開放,匿名的代碼塊,可以接受參數(shù),返回值并分配給變量

          簡而言之,他說一個匿名的代碼塊,可以接受參數(shù),有返回值。在DSL中,一個DSL腳本就是一個閉包。

          比如:

          //閉包賦值def closure = {    printf("hello")}//調(diào)用closure()

          2、括號語法

          當調(diào)用的方法需要參數(shù)時,Groovy 不要求使用括號,若有多個參數(shù),那么參數(shù)之間依然使用逗號分隔;如果不需要參數(shù),那么方法的調(diào)用必須顯示的使用括號。

          def add(number) { 1 + number }
          //DSL調(diào)用def res = add 1println res


          也支持級聯(lián)調(diào)用方式,舉例來說,a b c d 實際上就等同于 a(b).c(d)

          //定義total = 0def a(number) {    total += number    return this}def b(number) {    total *= number    return this}
          //dsla 2 b 3println total

          3、無參方法調(diào)用

          我們結合 Groovy 中對屬性的訪問就是對 getXXX 的訪問,將無參數(shù)的方法名改成 getXXX 的形式,即可實現(xiàn)“調(diào)用無參數(shù)的方法不需要括號”的語法!比如:

          def getTotal() { println "Total" }
          //DSL調(diào)用total

          4、MOP

          MOP:元對象協(xié)議。由 Groovy 語言中的一種協(xié)議。該協(xié)議的出現(xiàn)為元編程提供了優(yōu)雅的解決方案。而 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}

          5、定義和腳本分離

          @BaseScript 需要在注釋在自定義的腳本類型變量上,來指定當前腳本屬于哪個Delegate,從而執(zhí)行相應的腳本命令,也使IDE有自動提示的功能:

          腳本定義abstract class DslDelegate extends Script {  def setName(String name){        println name    }}

          腳本:

          import dsl.groovy.SetNameDelegateimport groovy.transform.BaseScript
          @BaseScript DslDelegate _
          setName("name")

          6、閉包委托

          使用以上介紹的方法,只能在腳本里執(zhí)行單個命令,如果想在腳本里執(zhí)行復雜的嵌套關系,比如Gradle中的dependencies,就需要@DelegatesTo支持了,@DelegatesTo執(zhí)行了腳本里定義的閉包用那個類來解析。

          上面提到一個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}


          7、加載并執(zhí)行腳本

          腳本可以在IDE里直接執(zhí)行,大多數(shù)情況下DSL腳本都是以文本的形式存在數(shù)據(jù)庫或配置中,這時候就需要先加載腳本再執(zhí)行,加載腳本可以通過以下方式:

           CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); compilerConfiguration.setScriptBaseClass(DslDelegate.class.getName()); GroovyShell shell = new GroovyShell(GroovyScriptRunner.class.getClassLoader()); Script script = shell.parse(file);

          給腳本傳參數(shù),并得到返回結果:

          Binding binding = new Binding();binding.setProperty("key", anyValue);Object res = InvokerHelper.createScript(script.getClass(), binding).run()

          二、總結

          通過以上的原理,你應該能設計出自己的DSL了,通多DSL可以設計出非常簡潔的API給用戶,在執(zhí)行的時候調(diào)用DSL內(nèi)部的復雜功能,這些功能的背后邏輯隱藏在了自己編寫的Delegate中。

          為了加深印象,我寫了個小的開源項目,把上面知識點串起來,構建了一個較完整的流程,如果還有什么不懂的地方,歡迎留言交流。

          項目地址:https://github.com/sofn/dsl-groovy

          本文作者:木小豐,美團Java高級工程師,關注架構、軟件工程、全棧等,不定期分享軟件研發(fā)過程中的實踐、思考。

          推薦閱讀:

          華為前中央硬件院院長李靖:做一家500億美金的公司

          華為內(nèi)部幾近滿分的項目管理PPT,牛逼了

          華為15年招聘經(jīng)驗總結:可用之才,必備5個特質

          不是你需要中臺,而是一名合格的架構師(附各大廠中臺建設PPT)

          世界的真實格局分析,地球人類社會底層運行原理

          世界先進生產(chǎn)力的入門法則,如何精準識人


          瀏覽 21
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.欧美在线 | 中文字幕欧美日韩VA免费视频 | www.成人黄色 | 中文无码短视频 | 免费在线a |