groovy动态脚本执行难题:GroovyShell和GroovyClassLoader都不希望在传入类加载器的上下文中



我正在尝试获得一个动态生成的groovy脚本,以继承类并实现调用java程序的接口。我传入了评估groovy脚本的类的类加载器,但没有用。我想知道我是否可以问一位Groovy专家我可能做错了什么?

代码如下所示。在这两种情况下,在评估脚本时,都无法识别在调用代码上下文中定义的类"X"。我收到的消息如下"Script1.groovy:3:无法解析类X"

import org.junit.Test
import java.lang.reflect.Method
public class GroovyPuzzler {
    public static class X {
    String hello = "said-hello"
    }

    @Test
    public void test1() {
    GroovyShell shell = new GroovyShell(this.getClass().getClassLoader());
    Object script = shell.evaluate(
        """
def sayHello() {
        println new X().hello;
}
return  this
""");
    Method m = script.getClass().getMethod("sayHello");
    m.invoke(script);
    }

    @Test
    public void test2() {
    String script =
        """
public class Boo {
    def sayHello() {
        println new X().hello;
     }
}
"""
    ClassLoader parent = getClass().getClassLoader();
    GroovyClassLoader loader = new GroovyClassLoader(parent);
    Class groovyClass = loader.parseClass(script);
    GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
    Object[] args = {};
    groovyObject.invokeMethod("sayHello", args);
    }
}

不知道如何从以这种方式调用的脚本中捕获输出(SystemOutputInterceptor???),所以我将println更改为throw,以说明它确实有效。

您需要做的是import您想要使用的类。代码如下:

package sample
import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.ImportCustomizer
import org.junit.Test
import java.lang.reflect.Method
public class GroovyPuzzler {
    public static class X {
        def hello2() {
            throw new RuntimeException("bang!")
        }
    }
    @Test 
    public void test1() {
        def customizer = new ImportCustomizer()
        customizer.addImport('X', 'sample.GroovyPuzzler.X')
        def configuration = new CompilerConfiguration()
        configuration.addCompilationCustomizers(customizer)
        GroovyShell shell = new GroovyShell(configuration)
        Object script = shell.evaluate(
        """
            def sayHello() {
                new X().hello2()
            }
            return this
        """
        )
        try {
           Method m = script.getClass().getMethod("sayHello")
           m.invoke(script)
           fail()
        } catch (Exception e) {
           assertTrue(e.cause.message.equals('bang!'))
        }
    }
}

最新更新