groovy闭包

为什么会开始学习闭包,因为在看到这个代码的时候我总是看不懂是什么意思:

1
2
3
4
5
6
gradle.taskGraph.beforeTask {
println("任务之前执行")
}
gradle.taskGraph.afterTask {Task task,TaskState state->
println("任务之后执行")
}

这里你可以点开源码,比如这个afterTask:

1
2
3
4
5
6
class TaskExecutionGraph{
void beforeTask(Closure var1);
void beforeTask(Action<Task> var1);
void afterTask(Closure var1);
void afterTask(Action<Task> var1);
}

这里可以看到传入的参数是一个叫Closure的类,这个就是Groovy里面的闭包.
这里举个闭包的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//lala.gradle
class Person{
String getName(Closure closure){
closure("cc","dd")
}
}
def bibao = {
x , y ->
println("Hello Closure ,the param valus is: "+x+","+y)
}
new Persion().getName(bibao)

// 运行后输出:
Hello Closure ,the param valus is:cc,dd

上面的也可以这么写:

1
2
3
4
5
6
7
8
class Person{
String getName(Closure closure){
closure("cc","dd")
}
}
new Persion().getName{x,y->
println("Hello Closure ,the param valus is: "+x+","+y)
}

看了上面这个例子你对闭包应该了解了,和kotlin里面的闭包差不多. 闭包


再回到上面的代码:

1
2
3
gradle.taskGraph.afterTask {Task task,TaskState state->
println("任务之后执行")
}

我们在看到源码的时候,看到的是afterTask里面传的参数是Closure,也就是一个闭包,那我们怎么知道这个闭包到底该怎么写呢.这个时候就需要看官方文档了:https://docs.gradle.org/current/javadoc/org/gradle/api/execution/TaskExecutionGraph.html#beforeTask-groovy.lang.Closure-
找到afterTask方法:
captrue.png
可以看到官方文档写清楚了,他的参数有哪些.


现在看另外一个方法: (这个方法是用来配置远程仓库的)

1
2
3
repositories {
mavenCentral()
}
1
2
3
class Project{
void repositories(Closure var1);
}

可以看到这个方法是属于project对象的.
打开官方文档找下这个方法:

captrue.png

文档里面很清楚的讲了RepositoryHandler做为闭包的委托传递给闭包.

这里出现了一个新的知识点做为闭包的委托传递给闭包.
闭包委托:
groovy的闭包委托有thisObject,owner,delegate三个属性.当在闭包内调用方法时,由他们来确定使用哪个对象来处理.默认情况owner和delegeta是相等的.但是delegate是可以进行修改的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//闭包委托
def method1(){
println "Context this :${this.getClass()} in root"
println "method1 in root"
}

class Delegate{
def method1(){
println "Delegate this : ${this.getClass()} in Delegate"
println "method1 in Delegate"
}

def test(Closure<Delegate> closure){
closure(this)
}
}

task helloDelegate <<{
new Delegate().test{
println "thisObject :${thisObject.getClass()}"
println "owner:${owner.getClass()}"
println "delegate:${delegate.getClass()}"
method1()
it.method1()
}
}
//输出
thisObject :class build_apnm7l2hrtoaa0bd51bpb5xcf
owner:class build_apnm7l2hrta
delegate:class build_apnm7
Context this :class build_apnm7l2hrtoaa0bd51bpb5xcf in root
method1 in root
Delegate this : class Delegate in Delegate
method1 in Delegate

可以看到thisObject优先级是最高的.
在DSL中,比如gradle,一般会指定delegate为当前it,这样我们就可以在闭包中对该it进行配置和方法调用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person {
String personName
int personAge

def dumpPerson(){
println "name is ${personName}, age is ${personAge}"
}
}

def person(Closure<Person> closure){
Person p = new Person()
closure.delegate = p
//委托模式优先
closure.setResolveStrategy(Closure.DELEGATE_FIRST)
closure(p)
}

task configClosure << {
person{
personName="张三"
personAge = 20
dumpPerson()
}
}

在回到上面讲的方法:

1
2
3
repositories {
mavenCentral()
}

官方文档讲了RepositoryHandler做为了闭包的委托传递给了闭包,所以在{}里面可以用到的方法就都是在RepositoryHandler对象申明的方法了.不信你可以打开RepositoryHandler类看下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public interface RepositoryHandler extends ArtifactRepositoryContainer {
FlatDirectoryArtifactRepository flatDir(Map<String, ?> var1);

FlatDirectoryArtifactRepository flatDir(Closure var1);

FlatDirectoryArtifactRepository flatDir(Action<? super FlatDirectoryArtifactRepository> var1);

ArtifactRepository gradlePluginPortal();

ArtifactRepository gradlePluginPortal(Action<? super ArtifactRepository> var1);

/** @deprecated */
@Deprecated
MavenArtifactRepository jcenter(Action<? super MavenArtifactRepository> var1);

/** @deprecated */
@Deprecated
MavenArtifactRepository jcenter();

MavenArtifactRepository mavenCentral(Map<String, ?> var1);

MavenArtifactRepository mavenCentral();

MavenArtifactRepository mavenCentral(Action<? super MavenArtifactRepository> var1);

MavenArtifactRepository mavenLocal();

MavenArtifactRepository mavenLocal(Action<? super MavenArtifactRepository> var1);

MavenArtifactRepository google();

MavenArtifactRepository google(Action<? super MavenArtifactRepository> var1);

MavenArtifactRepository maven(Closure var1);

MavenArtifactRepository maven(Action<? super MavenArtifactRepository> var1);

IvyArtifactRepository ivy(Closure var1);

IvyArtifactRepository ivy(Action<? super IvyArtifactRepository> var1);

void exclusiveContent(Action<? super ExclusiveContentRepository> var1);
}

是不是看到了我们熟知的方法:jcenter mavenCentral.所以上面的代码完整点可以这么写:

1
2
3
repositories {RepositoryHandler->
RepositoryHandler.mavenCentral()
}