简体   繁体   English

在运行时将Groovy脚本导入另一个Groovy脚本

[英]Import a Groovy script into another Groovy Script at Runtime

I have a Groovy file that looks like this (currently). 我有一个看起来像这样(当前)的Groovy文件。

main.groovy main.groovy

import org.packages.mystuff.JavaClassIAmUsing;
public class MyObject {

    def rate(item){
        def o = evaluate(new File (new File(getClass().protectionDomain.codeSource.location.path).parent),"CommonFunctions.groovy");
        println o.whoami();

    }
}

i have another groovy file called 我有另一个groovy文件叫

CommonFunctions.groovy CommonFunctions.groovy

def whoami() {return 'no body';}

I'm trying to include the CommonFunctions script in to main script, BUT the location of the script are not known at build time (ie i can not hardcode a absolute file path in the script or absoulte path of the java process in relation to where the scripts will be stored). 我正在尝试将CommonFunctions脚本包含在脚本中,但是脚本的位置在构建时是未知的(即我不能硬编码脚本中的绝对文件路径或java进程的absoulte路径相对于哪里脚本将被存储)。

All i know is that the scripts will be together or at a location relative to the calling script (say sub directory). 我所知道的是脚本将在一起或在相对于调用脚本的位置(比如子目录)。

I've attempted to try and location the calling script location, but i get the error 我试图尝试定位调用脚本位置,但我收到错误

  No signature of method: MyObject.evaluate()

How can i referance this script, considering the main script is accessed at runtime using a GroovyClassLoader.parseClass(File) method. 考虑到在运行时使用GroovyClassLoader.parseClass(File)方法访问主脚本,我如何重新编写此脚本。

I'm not really sure why you want to do it this way, I think it would be much simpler to make a class of CommonsFunctions that you could instantiate normally and use everywhere. 我不确定你为什么要这样做,我认为制作一类CommonsFunctions可以更简单,你可以正常实例化并在任何地方使用。

However, it is possible to achieve what you want; 但是, 可能实现你想要的; with Groovy, there are not that many limitations... 有了Groovy,没有那么多限制......

There are two problems with your suggested solution: 建议的解决方案有两个问题:

  1. getClass() inside your MyObject class naturally refers to ... the MyObject class, so your attempt to find the location of the script will fail. MyObject类中的getClass()自然地引用了MyObject类,因此您尝试查找脚本的位置将失败。 You're on the right track, but you need to resolve the script location using the surrounding Script class. 您处于正确的轨道上,但您需要使用周围的Script类来解析脚本位置。
  2. evaluate doesn't really work the way you think it does. evaluate并不像你认为的那样真正起作用。 The result of the evaluate method is the result of the script, not an instance of the Script class. evaluate方法的结果是脚本的结果,而不是Script类的实例。 One way to remedy this, is to rewrite the methods in CommonFunction as closure properties. 解决这个问题的一种方法是将CommonFunction的方法重写为闭包属性。 These properties will be available in the shell Binding object when evaluating the script. 在评估脚本时,这些属性将在shell Binding对象中可用。

So, with these rewrites, you end up with something like this: 所以,通过这些重写,你最终会得到这样的结果:

main.groovy main.groovy

class MyObject {
    def scriptDir

    def rate(item) {
        def commonFunctionsScriptFile = new File(scriptDir, "CommonFunctions.groovy")
        def binding = new Binding()
        new GroovyShell(binding).evaluate(commonFunctionsScriptFile)
        println binding.variables.whoami()
    }
}

scriptFile = new File(getClass().protectionDomain.codeSource.location.path)
new MyObject(scriptDir: scriptFile.parentFile).rate(null)

Here, the script file location is resolved in the script, not in the inner class. 这里,脚本文件位置在脚本中解析,而不是在内部类中解析。

CommonFunctions.groovy CommonFunctions.groovy

whoami = { 'no body' }

Here, whoami is no longer a method, but a closure property which will be added to the binding. 在这里, whoami不再是一个方法,而是一个将被添加到绑定中的闭包属性。 Make sure that you don't prefix this property with def , since then it will be a local variable instead of a property added to the binding object. 确保使用def为此属性添加前缀,因为它将是一个局部变量而不是添加到绑定对象的属性。

Output after these rewrites is the expected: no body . 这些重写后的输出是预期的: no body

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM