概述
I would like to know how to create a Closure object at run-time from within a Java application, where the content of the Closure is not known ahead of time. I have found a solution but I doubt that it is optimal.
Background: I have written some Groovy code that parses a Domain Specific Language. The parsing code is statically compiled and included in a Java application. In the parser implementation I have classes acting as delegates for specific sections of the DSL. These classes are invoked using the following pattern:
class DslDelegate {
private Configuration configuration
def section(@DelegatesTo(SectionDelegate) Closure cl) {
cl.delegate = new SectionDelegate(configuration)
cl.resolveStrategy = Closure.DELEGATE_FIRST
cl()
}
}
I wish to call such a method directly from Java code. I am able to create a new DslDelegate object and then invoke the section() method. However I need to create and pass an argument that is an instance of Closure. I want the content to be initialised from a String object.
My Solution: The following Java code (utility) is working but I am asking for improvements. Surely this can be done in a cleaner or more efficient manner?
/**
* Build a Groovy Closure dynamically
*
* @param strings
* an array of strings for the text of the Closure
* @return a Groovy Closure comprising the specified text from {@code strings}
* @throws IOException
*/
public Closure> buildClosure(String... strings) throws IOException {
Closure> closure = null;
// Create a method returning a closure
StringBuilder sb = new StringBuilder("def closure() { { script -> ");
sb.append(String.join("n", strings));
sb.append(" } }");
// Create an anonymous class for the method
GroovyClassLoader loader = new GroovyClassLoader();
Class> groovyClass = loader.parseClass(sb.toString());
try {
// Create an instance of the class
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
// Invoke the object's method and thus obtain the closure
closure = (Closure>) groovyObject.invokeMethod("closure", null);
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
} finally {
loader.close();
}
return closure;
}
解决方案
You can use GroovyShell to create a Closure from strings:
public Closure> buildClosure(String... strings) {
String scriptText = "{ script -> " + String.join("n", strings) + " }";
return (Closure>) new GroovyShell().evaluate(scriptText);
}
最后
以上就是魔幻楼房为你收集整理的java动态开发groovy,如何从Java中的字符串动态创建Groovy闭包的全部内容,希望文章能够帮你解决java动态开发groovy,如何从Java中的字符串动态创建Groovy闭包所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复