GroovyClassLoader层次结构和CompilerConfiguration

时间:2014-07-24 08:23:58

标签: groovy

问题:

  • 使用明确设置GroovyClassLoader

  • 创建CompilerConfiguration GCLA
  • 使用不同的GroovyClassLoader创建另一个CompilerConfiguration GCLB ,设置BaseScriptClass并使用 GCLA 作为父级

- >在 GCLB 中加载的脚本将无法正确设置BaseScriptClass(但使用 GCLA 的潜在设置基础)

长篇故事:

我的应用程序使用四个Groovy脚本来允许自定义某些操作。每个脚本都提供一个小型DSL,每个脚本的DLS都不同。在应用程序中执行操作时,将调用相应的脚本。另外,一些常见的groovy脚本可以在应用程序启动时加载,用于存储公共数据或辅助函数的定义。

在应用程序启动时,脚本会严重受损。

我的第一个方法是让一个 GroovyClassLoader首先加载常见的groovy脚本,然后为每个脚本执行loadClass 。通过简单地将相应的元素添加到脚本运行的每个脚本的绑定中来创建DSL。 GroovyClassLoader使用带有 TypeCheck-Extensions CompilerConfiguration来检查脚本。

这很有效,但有两个严重的限制:

  • 必须根据脚本的名称执行类型检查(因为每个脚本的DSL都不同)

  • 类型检查脚本变得非常复杂,因为它必须处理所有四个DSL

为了摆脱命名限制,我试图为每个脚本(即每个DSL一个)使用不同的GroovyClassLoader(我的实际ClassLoader作为父级)并设置相应的ScriptBaseClass提供DSL的功能。这非常有效:类型检查代码大大减少,我可以为每个DSL提供不同的类型检查脚本,而且我不必弄乱脚本的名称。

但是我不能使用常见的groovy脚本。一旦我尝试使用通用脚本GroovyClassLoader作为DSL脚本的GroovyClassLoader的父级,DSL就不再能够获得正确的BaseScriptClass虽然它在CompilerConfiguration中明确地设定了。孩子GroovyClassLoader似乎使用了父BaseScriptClass的{​​{1}}。

有关如何使其正常工作的任何想法?

更新 在我的原帖中,我没有提到我使用scala。实际上我尝试了以下代码片段:

GroovyClassLoader

这不起作用,子类ClassLoader似乎完全忽略了val rootConfig = { val cf = new CompilerConfiguration(CompilerConfiguration.DEFAULT) cf.setSourceEncoding("UTF-8") cf.addCompilationCustomizers(new ASTTransformationCustomizer(classOf[CompileStatic])) cf } val childConfig = { val cfg = new CompilerConfiguration(CompilerConfiguration.DEFAULT) cfg.setSourceEncoding("UTF-8") cfg.setScriptBaseClass("NonExisting") cfg.addCompilationCustomizers(new ASTTransformationCustomizer(classOf[CompileStatic])) cfg } val rootGCL = new GroovyClassLoader(getClass.getClassLoader, rootConfig, false) val childGCL = new GroovyClassLoader(rootGCL, childConfig, false) :它没有抱怨不存在的CompilerConfiguration,如果我关闭rootConfig中的静态编译,它将会甚至没有进行静态检查。

如果我将ClassLoader创建移动到Java文件,一切都按预期工作

1 个答案:

答案 0 :(得分:0)

GroovyClassLoader有几个构造函数。例如,一个用于ClassLoader,另一个用于GroovyClassLoader。 GroovyClassLoader版本将从中获取配置。但是,如果你这样做new GroovyClassLoader((ClassLoader) parent)或者自己进行配置。为此,甚至可以将null作为配置。构造函数逻辑将使用CompilerConfiguration.DEFAULT然后配置GroovyClassLoader:new GroovyClassLoader(parent,null)如果您想确保没有向GroovyClassLoader添加任何奇怪的路径,请使用带有布尔new GroovyClassLoader(parent,null,false)的变体