在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,寻找些乐子吧。
整体项目代码在:
回复 can i purchase generic cytotec online 取消回复