【发布时间】:2012-02-18 17:32:33
【问题描述】:
文件1.groovy
def method() {
println "test"
}
文件2.groovy
method()
我想在运行时从 File1.groovy 加载/包含函数/方法,相当于 rubys/rake 的加载。它们位于两个不同的目录中。
【问题讨论】:
文件1.groovy
def method() {
println "test"
}
文件2.groovy
method()
我想在运行时从 File1.groovy 加载/包含函数/方法,相当于 rubys/rake 的加载。它们位于两个不同的目录中。
【问题讨论】:
如果您不介意 file2 中的代码位于 with 块中,您可以这样做:
new GroovyShell().parse( new File( 'file1.groovy' ) ).with {
method()
}
另一种可能的方法是将file1.groovy 更改为:
class File1 {
def method() {
println "test"
}
}
然后在file2.groovy 中,您可以使用mixin 添加来自file1 的方法
def script = new GroovyScriptEngine( '.' ).with {
loadScriptByName( 'file1.groovy' )
}
this.metaClass.mixin script
method()
【讨论】:
您可以使用 GroovyShell 在 Groovy 中评估任何表达式或脚本。
文件2.groovy
GroovyShell shell = new GroovyShell()
def script = shell.parse(new File('/path/file1.groovy'))
script.method()
【讨论】:
file1.groovy 既不需要是一个实际的类,也不需要它的方法是静态的。
如果file1.groovy 是一个实际的类class File1 {...},那将是最简单的。
鉴于此,另一种方法是将文件加载到GroovyClassLoader:
this.class.classLoader.parseClass("src/File1.groovy")
File1.method()
File1.newInstance().anotherMethod()
【讨论】:
.parseClass(new File("..")) 的方法,请参阅stackoverflow.com/questions/13993611/…
我迟到了,但是。这就是我们一直在实现您的要求的方式。所以,我有一个像这样的 file1.gsh:
文件 1:
println("this is a test script")
def Sometask(param1, param2, param3)
{
retry(3){
try{
///some code that uses the param
}
catch (error){
println("Exception throw, will retry...")
sleep 30
errorHandler.call(error)
}
}
}
return this;
而在另一个文件中,这些函数可以通过先实例化来访问。所以在文件 2 中。
文件2:
def somename
somename = load 'path/to/file1.groovy'
//the you can call the function in file1 as
somename.Sometask(param1, param2, param3)
【讨论】:
return this,所以load 正在返回null。
load 'path/to/file' 工作完美,不知道为什么这么难找到,虽然如果我没记错的话,当前缀为 ./ 时它不起作用
这是我正在使用的。
1:将any_path_to_the_script.groovy写成一个类
2:在调用脚本中,使用:
def myClass = this.class.classLoader.parseClass(new File("any_path_to_the_script.groovy"))
myClass.staticMethod()
它在 Jenkins Groovy 脚本控制台中运行。我没有尝试过非静态方法。
【讨论】:
@tim_yates 使用metaClass.mixin 的答案应该可以在不需要对file1.groovy 进行任何更改的情况下工作(即mixin 与脚本对象),但不幸的是metaClass.mixin 中有一个错误导致SO这种情况下的错误(请参阅GROOVY-4214 关于此特定问题)。但是,我使用以下 selective mixin:
def loadScript(def scriptFile) {
def script = new GroovyShell().parse(new File(scriptFile))
script.metaClass.methods.each {
if (it.declaringClass.getTheClass() == script.class && ! it.name.contains('$') && it.name != 'main' && it.name != 'run') {
this.metaClass."$it.name" = script.&"$it.name"
}
}
}
loadScript('File1.groovy')
method()
上述解决方案无需更改File1.groovy 或File2.groovy 中的调用者(除了需要引入对loadScript 函数的调用)。
【讨论】:
loadScript重命名为importScript可能更准确。