Как использовать импорт внутри динамически загружаемого файла Groovy
Я пытаюсь придумать, как мои пользователи могут добавлять плагины в основное приложение Groovy, динамически загружая их исходный файл. Но в их отличном файле содержатся операторы import, и я не знаю, как заставить их работать даже с явно хорошим путем к классам.
Основное приложение - это скрипт оболочки bin/top.sh:
#!/bin/bash
groovy-2.4.1/bin/groovy -cp lib lib/Top.groovy
Класс lib/Top.groovy:
public class Top {
public static void main(String[] args) {
ClassLoader parent = getClass().getClassLoader()
GroovyClassLoader loader = new GroovyClassLoader(parent)
Class groovyClass = loader.parseClass(new File("UserPlugin.groovy"))
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance()
groovyObject.invokeMethod("run",args)
}
}
Пользовательский класс UserPlugin.groovy:
// The following import can be found in the classpath
// passed by the shell script (under lib/, next to Top.groovy)
import Lib
class UserPlugin {
def UserPlugin() {
Lib lib = new Lib()
}
def run(String [] args) {
println("Running with: "+args)
}
}
И lib/Lib.groovy:
class Lib {
def Lib() {
println("Lib")
}
}
Когда я бегу с bin/top.sh
, Я получил: UserPlugin.groovy: 3: unable to resolve class Lib
Когда я добавлю lib
к загрузчику классов, как это так loader.addClasspath('lib')
Скорее катастрофично:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
java.lang.RuntimeException: java.lang.NoClassDefFoundError: groovy/lang/GroovyObject
at org.codehaus.groovy.control.CompilationUnit.convertUncaughtExceptionToCompilationError(CompilationUnit.java:1088)
Как это может работать при сохранении всего сценария, а не скомпилированного? Это вообще возможно?
1 ответ
Извините, у меня нет времени, чтобы найти ошибку, но я думаю, что проблема в настройке контекстного загрузчика классов. GroovyShell.run позаботится об этом за вас, и я рекомендую использовать его тиражирование.
Top.groovy
public class Top {
public static void main(String[] args) {
new GroovyShell().run(new File("UserPlugin.groovy"), args)
}
}
Если вы хотите сделать Top.groovy сценарием, а не классом, то вы можете сделать это:
Top.groovy
run(new File("UserPlugin.groovy"), args)
Тогда UserPlugin.groovy должен быть либо классом (с основным методом), либо скриптом, чтобы использовать стандартную логику вызова Groovy.