通过反射从java执行编译的groovy脚本

时间:2018-04-19 07:50:00

标签: java groovy reflection

我有很多groovy脚本,用GMaven编译(位于src/main/groovy/somepackage),每个脚本都有run(String, String)函数,没有类:

// script1.groovy
def run(String name, String arg) {
  // body
}


// script2.groovy
def run(String name, String arg) {
  // body
}

我可以使用Reflections库找到它们并解析它们的类型:

final Set<String> scripts = new Reflections(
  "somepackage",
   new SubTypesScanner(false)
).getAllTypes();
for (String script : scripts) {
  run(Class.forName(name));
}

然后我遇到了一些执行问题:我无法创建scipt实例,因为它没有公共构造函数(只有私有的groovy.lang.Reference参数)而且我不能找到此类型的run方法。

问题:如何使用反射正确地从Java执行编译的groovy脚本(使用单个方法,没有类)?

1 个答案:

答案 0 :(得分:1)

您可以使用以下命令从给定的包加载已编译的Groovy脚本:

Reflections.getSubTypesOf(groovy.lang.Script.class)

它返回Set<Class<? extends Script>>,因此您可以迭代这些类,实例化它们并使用Class.invokeMethod(String name, Object args)

调用方法
  

注意:您无法像script.run(string1, string2)那样调用此方法,因为此方法在父groovy.lang.Script类中不存在。

您可以在下面找到一个示例:

import groovy.lang.Script;
import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;

import java.util.Set;

public class LoadGroovyScriptExample {

    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        Set<Class<? extends Script>> scripts = new Reflections("somepackage", new SubTypesScanner(false))
                .getSubTypesOf(Script.class);

        for (Class<? extends Script> script : scripts) {
            script.newInstance().invokeMethod("run", new Object[] { "test", "123" });
        }
    }
}

somepackage / script1.groovy

package somepackage

def run(String name, String arg) {
    println "running script1.groovy: ${name}, ${arg}"
}

somepackage / script2.groovy

package somepackage

def run(String name, String arg) {
    println "running script2.groovy: ${name}, ${arg}"
}

控制台输出

[main] INFO org.reflections.Reflections - Reflections took 93 ms to scan 1 urls, producing 1 keys and 2 values 
running script2.groovy: test, 123
running script1.groovy: test, 123