如何使用 Groovy 动态对象来调用需要具体类型的方法(不引用它们)

How to use Groovy dynamic objects to call methods requiring concrete types (without referencing them)

给定以下代码:

def model = readMavenPom file: 'pom.xml'
dep = [
   groupId : "org.foo",
   artifactId :  "bar",
   version : "1.0" ]

我想打电话给Model.addDependency

model.addDependency(dep)

这给出了错误

Caught: groovy.lang.MissingMethodException: No signature of method: org.apache.maven.model.Model.addDependency() is applicable for argument types: (java.util.LinkedHashMap) values: [[groupId:org.foo, artifactId:bar, version:1.0]]

现在可以做到

model.addDependency(dep as Dependency)

引用class时。它可以正常工作。本地。

不幸的是,我必须在 Jenkins 上执行它,我 运行 对此 issue。所以基本上,如果我引用 Dependency class,我会 运行 进入一些 class 加载问题。建议使用 "dynamic typing".

所以可以在不引用 class 的情况下调用 addDependency?

问题是加载模型 class(我们称之为 "A")的 classloader 与您引用时脚本尝试使用的加载器不同依赖项 class ("B")。因此,您可以使用 classloader-B 创建 Dependency-B,但是 Model-A 需要 Dependency-A。

我们可以使用反射来获取对 Dependency-A class 的引用,然后使用相同的 属性 映射创建它的实例,如下所示:

def model = readMavenPom file: 'pom.xml'
dep = [
   groupId : "org.foo",
   artifactId :  "bar",
   version : "1.0" ]
model.addDependency(model.&addDependency.parameterTypes[0].n‌​ewInstance(dep))

在Groovy中,&addDependency是一个方法引用,反射风格。我们肯定知道只有一个同名的方法并且它只有一个参数,所以我们只需要第一个参数的 class 并调用 newInstance,它的工作方式与 "as" 关键字相同.