Groovy和DSL二: Closure Delegate

Groovy和DSL一: 模拟Gradle中,我们搭建了一个DSL脚本的解析框架。现在我们来专注于Closuer的实现,主要的方法是通过Closure Delegate

Delegate

在Project.groovy中,closure是没有实现的:

    void dependencies(Closure cl){
        println "dependencies get called"
    }

由纯groovy调用构成的closure很好处理,直接调用call函数,比如:

def cl={
    println "hello"
    println "world"
}

cl.call()

但如果closure中包含自定义的函数,那就不行了,比如我们的dependencies中,包含着testImplementation和implementation两个函数,直接运行closure.run是无法识别的

dependencies {
    // Use JUnit test framework.
    testImplementation 'junit:junit:4.13.2'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:30.1.1-jre'
}

这时候就要用我们的Delegate了,基本的处理范式是这样的:

  • 创建一个类,实现closure中的自定义的函数
  • 设置closure的delegate到该类
  • 运行closure,当遇到自定义关键字时,会映射到delegate类中

示例如下:

def cl = {
    println "hello"
    println "world"

    //foo是自定义函数
    foo "hello closuer"
}

//使用delegate处理自定义函数
class ClDelegate{
    void foo(String param){
        println param
    }
}

ClDelegate clDlg = new ClDelegate()
cl.delegate = clDlg
cl.resolveStrategy = Closure.DELEGATE_ONLY
cl.call()

Bradle实现

明白了套路之后,回头看看我们的bradle配置文件:

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit test framework.
    testImplementation 'junit:junit:4.13.2'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:30.1.1-jre'
}

tasks.register("t1"){
    println "task t1 executed"
}

tasks.register("t2"){
    doLast{
        println "task t2 executed"
    }
}

要实现的Delegate如下:

  • repositories delegate,实现其中的mavenCentral函数
  • dependencies delegate,实现其中的testImplementation和implementation函数
  • task delegate,实现doLast函数

最终的代码如下:

package groovydls
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentMap

abstract class Project extends Script{
    TaskContainer tasks

    Project(){
        tasks = new TaskContainer()
    }

    void repositories(Closure cl){
       RepositoriesDelegate repDlg = new RepositoriesDelegate()
       cl.delegate = repDlg
       cl.resolveStrategy = Closure.DELEGATE_ONLY
       cl.call()
    }

    void dependencies(Closure cl){
       DependenciesDelegate depDlg = new DependenciesDelegate()
       cl.delegate = depDlg
       cl.resolveStrategy = Closure.DELEGATE_ONLY
       cl.call()
    }
}

class TaskContainer{
   static final ConcurrentMap<String, Closure> taskMap = [:] as ConcurrentHashMap
   void register(String name, Closure cl){
        taskMap."$name" = cl
   }

   void run(String name){
        Closure cl = taskMap."$name"
        TaskDelegate tDlg = new TaskDelegate()
        cl.delegate = tDlg
        cl.resolveStrategy = Closure.DELEGATE_ONLY
        cl.call()
   }
}


class RepositoriesDelegate{
    void mavenCentral(){
        println "mavenCentral get called"
    }
}

class DependenciesDelegate{
    void implementation(String id){
        println "implementation get called, id:"+id
    }

    void testImplementation(String id){
        println "testImplementation get called, id:"+id
    }
}

class TaskDelegate{
    void doLast(Closure cl){
        cl.call()
    }
}

小结

至此,一个bradle就完成了,在bradle.build中添加更多的task,寻找些乐子吧。

整体项目代码在:

Ref



《 “Groovy和DSL二: Closure Delegate” 》 有 4 条评论

  1. I never made it to work that day where can i buy cheap cytotec price Lukassen HGM, Schönbeck Y, Adang EMM, Braat DDM, Zielhuis GA, Kremer JAM

  2. Other suitable PPIs or histamine 2 antagonists may be therapeutic alternatives that can be used to avoid adverse consequences can i purchase generic cytotec for sale

  3. It won t be long before elevated systolic blood pressure you join the rest of the kings, Create a spiritual connection how to take priligy

  4. This study adds knowledge to the existing evidence of the associations between cardiac drug therapy and anxiety priligy review members

回复 agodelo 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About Me

一位程序员,会弹吉他,喜欢读诗。
有一颗感恩的心,一位美丽的妻子,两个可爱的女儿
mail: geraldlee0825@gmail.com
github: https://github.com/lisuxiaoqi
medium: https://medium.com/@geraldlee0825