如何在动态加载的 groovy 文件中使用导入
How to use import inside a dynamically loaded groovy file
我正在尝试为我的用户想出一种方法,通过动态加载他们的源文件向主 groovy 应用程序提供插件。但是他们的 groovy 文件包含 import 语句,我不知道如何让它们工作,即使使用明显好的 classpath.
主要应用程序是一个 shell 脚本,bin/top.sh:
#!/bin/bash
groovy-2.4.1/bin/groovy -cp lib lib/Top.groovy
lib/Top.groovy class:
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)
}
}
用户classUserPlugin.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
当我像这样 loader.addClasspath('lib')
将 lib
添加到 class 加载程序时,这是相当灾难性的:
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)
如何在保持所有脚本而不是编译的情况下工作?这可能吗?
抱歉,我没有时间查找错误,但我认为问题出在上下文 classloader 的设置上。 GroovyShell.run 会为您处理,我建议不要复制该代码。
Top.groovy
public class Top {
public static void main(String[] args) {
new GroovyShell().run(new File("UserPlugin.groovy"), args)
}
}
如果您愿意 Top.groovy 一个脚本而不是 class 那么您可以这样做:
Top.groovy
run(new File("UserPlugin.groovy"), args)
然后 UserPlugin.groovy 需要是 class(带有 main 方法)或脚本才能使用标准 Groovy 调用逻辑。
我正在尝试为我的用户想出一种方法,通过动态加载他们的源文件向主 groovy 应用程序提供插件。但是他们的 groovy 文件包含 import 语句,我不知道如何让它们工作,即使使用明显好的 classpath.
主要应用程序是一个 shell 脚本,bin/top.sh:
#!/bin/bash
groovy-2.4.1/bin/groovy -cp lib lib/Top.groovy
lib/Top.groovy class:
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)
}
}
用户classUserPlugin.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
当我像这样 loader.addClasspath('lib')
将 lib
添加到 class 加载程序时,这是相当灾难性的:
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)
如何在保持所有脚本而不是编译的情况下工作?这可能吗?
抱歉,我没有时间查找错误,但我认为问题出在上下文 classloader 的设置上。 GroovyShell.run 会为您处理,我建议不要复制该代码。
Top.groovy
public class Top {
public static void main(String[] args) {
new GroovyShell().run(new File("UserPlugin.groovy"), args)
}
}
如果您愿意 Top.groovy 一个脚本而不是 class 那么您可以这样做:
Top.groovy
run(new File("UserPlugin.groovy"), args)
然后 UserPlugin.groovy 需要是 class(带有 main 方法)或脚本才能使用标准 Groovy 调用逻辑。