首页 > 解决方案 > 任何人都可以解释 groovy 闭包的魔力/詹金斯

问题描述

我想了解基于 groovy DSL 和闭包的 Jenkins 管道的一部分代码。

我有一个詹金斯文件如下:

foo {
  var1 = "foo value 1"
  var2 = "foo value 2"
}

我的 Jenkins 共享库中有一个 groovy 脚本(vars 目录中的 foo.groovy):

def call(body) {
   def config = [:]
   body.resolveStrategy = Closure.DELEGATE_FIRST
   body.delegate = config
   body()

   println config.var1 // display foo value 1 : for me the magic is here !!
}

我想了解 groovy / jenkins 机制,即当调用闭包时,map config 是使用变量 var1 和 var2 设置的。

我(几乎)了解闭包机制和委托方法,但是我们怎么知道配置映射到闭包的委托字段的影响允许使用我的 Jenkinsfile 中声明的变量构建映射?

我希望我的问题很清楚!:)

问候,

史蒂夫

标签: jenkinsgroovy

解决方案


当一个属性在闭包中被引用,并且该引用无法在闭包中解析时,会尝试在不同的“地方”解析它

  1. this
  2. 闭包的delegate属性,可以重新分配
  3. 关闭的owner

在您的示例中,var1var2是无法在闭包中解析的引用示例。

以下将闭包的委托分配给config并确保这是用于解析未解析引用的第一个“位置”

def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config

因此,当我们在闭包中设置属性时var1var2它们是针对 解析的config,即设置为 this 的键值对Map

如果您的示例更改为:

foo {
   def var3 = "some value"

   var1 = "foo value 1"
   var2 = "foo value 2"
   var3 = "some value"
}

var3不会解决,config因为它可以在闭包内解决。

更新

回应您的评论(我认为):为什么将闭包的委托设置为地图会导致将键值对添加到该地图?

var1 = "foo value 1"不能在闭包内解决时,它会根据地图解决,因为这个

def config = [:]
body.resolveStrategy = Closure.DELEGATE_FIRST
body.delegate = config

所以这实际上意味着我们在打电话

config.var1 = "foo value 1"

这是 Groovy 的简写

config.put("var1", "foo value 1")

如果您更改代码以直接调用该方法,可能会更容易理解put,例如

def foo = {
  put('var1', "foo value 1")
}

def call(body) {
   def config = [:]
   body.resolveStrategy = Closure.DELEGATE_FIRST
   body.delegate = config
   body()

   println config.var1 // display foo value 1 : for me the magic is here !!
}

call(foo)

如果您在 Groovy 控制台中运行此代码,您会看到它还会打印“foo value 1”。

如果你还在苦苦挣扎,也许这个问题会有所帮助。


推荐阅读