Выполнить скомпилированный скрипт groovy из java через отражение

У меня есть много отличных скриптов, скомпилированных с помощью 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));
}

тогда у меня есть некоторые проблемы с выполнением: я не могу создать экземпляр сценария, потому что у него нет общедоступного конструктора (есть только частный с параметрами groovy.lang.Reference), и я не могу найти метод run в этом типе.

Вопрос: как правильно выполнить скомпилированный скрипт groovy (с одним методом и без класса) из Java с использованием отражения?


person Kirill    schedule 19.04.2018    source источник


Ответы (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" });
        }
    }
}

какой-то пакет/script1.groovy

package somepackage

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

какой-то пакет/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
person Szymon Stepniak    schedule 19.04.2018