1

我试图想出一种方法,让我的用户通过动态加载他们的源文件来向主 groovy 应用程序提供插件。但是他们的 groovy 文件包含导入语句,我不知道如何让它们工作,即使有一个明显很好的类路径。

主应用程序是一个 shell 脚本 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)

这如何在保持所有脚本编写而不是编译的情况下工作?这甚至可能吗?

4

1 回答 1

0

抱歉,我没有时间找到错误,但我认为问题出在上下文类加载器的设置上。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 需要是一个类(带有一个 main 方法)或一个脚本才能使用标准的 Groovy 调用逻辑。

于 2015-02-27T02:53:37.593 回答