美文网首页
Gradle —— 代理模式(Delegate 机制)

Gradle —— 代理模式(Delegate 机制)

作者: 你可记得叫安可 | 来源:发表于2019-12-01 11:30 被阅读0次

以下代码使用 Gradle 5.4.1

task showDescription1 {
    doLast {
        description = 'this is task showDescription'
        println description
    }
}

task showDescription2 {
    doLast {
        println description
    }
}
showDescription2.description = 'this is task showDescription'


task showDescription3 {
    doLast {
        println description
    }
}
showDescription3 {
   description = 'this is task showDescription'
}

以上 3 个 Task 完成的功能相同,即在执行这个 Task 时打印 description 属性。但是它们对 description 的赋值时,所在的生命周期却不同。

  • showDescription1 的赋值是在执行阶段
  • showDescription2 的赋值是在配置阶段
  • showDescription3 的赋值也是在配置阶段
    事实上,对于每一个 TaskGradle 都会在 Project 中创建一个同名的 Porperty,我们可以将该 Task 当做一个 Property 来访问,showDescription2 便是这种情况。另外,Gradle还会创建一个同名的方法,该方法接收一个闭包,我们可以通过该方法来配置 TaskshowDescription3 便是这种情况。
    这里面有两个概念:Groovy 中的 Bean 概念 和 Groovy 闭包的 delegate 机制。
Bean 概念

这个 Bean 概念与 Kotlin 中的 Data Class 差不多,即 Groovy 会自动生成属性的 getter(), setter() 方法。所以上面我们可以直接访问 showDescription2

Delegate 机制

这里重点的是 Groovy 闭包的 Delegate 机制。简单来说,Delegate 机制可以使我们将一个闭包中的执行代码的作用对象设置成任意其他对象。

class Child {
   private String name
}

class Parent {
   Child child = new Child();

   void configChild(Closure c) {
      c.delegate = child
      c.setResolveStrategy Closure.DELEGATE_FIRST
      c()
   }
}

def parent = new Parent()
parent.configChild {
    name = "child name"
}

println parent.child.name

在上面的例子中,当我们调用 configChild() 时,我们并没有指明 name 属性是属于 Child 的,虽然它确实是设置的 Child.name 属性,但是从调用者来看,他传入闭包时,根本不知道 name 是属于哪个对象的。我们在 configChild 中做了手脚,使其不再访问 Parent 中的 nameParent 中也没有 name 属性),而是 Childname 属性。
configChild() 方法中,我们将该方法接受的闭包的 delegate 设置为了 child,然后将该闭包的 ResolveStrategy 设置为了 DELEGATE_FIRST。这样,在调用 configChild() 时,所跟闭包中代码被代理到了 child 上,即这些代码实际上是在 child 上执行的。

再举个例子,Project#configurations() 方法,实际上会将所跟闭包的 delegate 设置成 ConfigurationContainer,然后在该 ConfigurationContainer 上执行闭包中的代码。这里的 ConfigurationContainer 也是 Project 的一个属性。再比如,dependencies() 方法,该方法会将所跟闭包的 delegate 设置成 DependencyHandler
还有,Project 还定义了 configure(Object object, Closure configureClosure) 方法,该方法是专门用来配置对象的(比如 Task),它会将 configureClosuredelegate 设置成 object,之后 configureClosure 中的执行代码其实是在 object 上执行的。

结论

GroovyDelegate 机制的一个好处是可以增加所创建 DSL 的可读性。

相关文章

网友评论

      本文标题:Gradle —— 代理模式(Delegate 机制)

      本文链接:https://www.haomeiwen.com/subject/ozhzwctx.html