Laravel 执行流程(四)之 认识 Bind
备注:纯手打的学习笔记,如有错误之处请指正,谢谢。希望大家学的开心!
第三章的探索相信有很多学友只是知道一些基本流程,并未真正意义上知道其所以然,不过学习还需要循序渐进,先了解,在深入,最后总结,本章,咱们将要探秘 bind() 方法。
- Bind方法位于Container.php

Bind 第一次被使用是在 EventServiceProvider 类的 register() 方法里,千万别问我 EventServiceProvider 怎么找了,类开头一堆 use 中就有。
第三章说到注册2个基本的服务提供商,分别是事件( event )和路由( route ),都分别执行了各自的 $provider->register()。
首先看第一次执行 bind() 的代码上下文:

$this->app 怎么来的?这个成员属性是在抽象类 ServiceProvider 中定义好的,并在其构造函数中进行赋值:

大家可以查阅,所有的服务提供商都继承于这个类,而在 application 类中的 registerBaseServiceProviders() 传入了这个参数 $this:

接下来我们看见的是 singleton 并非 bind 方法,而 singleton 意为单例,在方法内部调用如下:

只不过是把 bind 的第三个参数设置为共享状态。
好,结合现在的情况,在分析下参数,给了一个 events 字符串,还有一个闭包函数,闭包需要传入一个参数 $app ,这个参数无非就是 application 的实例。
好,把这个来龙去脉弄清楚了,我们才能更清晰的分析 bind 内部逻辑。
Bind 开头进行了一个数组判断,为了大家看的清楚,我简单的举了个例子:

extractAlias 方法只是返回了这样一个数组:

很简单吧,提取后在重组别名:

代码带来的功能就是这样,具体的意义,我把注释翻译,大家尽量去理解:

接下来又进行了“删除陈旧的实例”,dropStaleInstances():

删除以后,判断了如下:

注释勉强理解:

为了把这里弄懂,我们现在假设 $concrete 确实为 null,然后看往下是怎么发展的。
接着下面又来了一段注释,不过太复杂,没有很好的英文底子我也是醉了,所以就不拿上来了。
直接看代码吧:

如果 $concrete 不是一个闭包,就封装成一个闭包,刚才我们假设了为 null,并且 $concrete = $abstract,那么在看一下 getClosure 方法:

我们以刚才的假设来虚拟场景,$concrete = $abstract,所以 $method=build,并且执行 $c->build() 方法,$c 是 application 实例,只是看从什么地方传的参数即可,所以刚才那个判断 null 的作用就是在,有 “build” 和 “make” 2种选择。
现在不应该又跳去看 build 方法,因为这段代码目前为止没有执行,只是把脚本提交到这里:

接下来要认识一个新数组 bindings:

Compact 创建一个由参数所带变量组成的数组。如果参数中存在数组,该数组中变量的值也会被获取,这里我们知道 $conrete 被封装成一个闭包了,而 $shared 是在 singleton 方法中传的 true,也就是1。所以现在bindings 数组形式如下:

这里有部分人可能会纠结,你刚才不是说 $concrete 为 null,怎么又变成了一个闭包对象;刚才仅仅只是用假设,来弄懂一个环节,所以正常来说这里就是这样。
最后:

Events 肯定没有解析过,所以这里的 rebound 反弹暂时不能过多讲解。
到现在为止,闭包内的代码依然没有执行,而 bind 方法也到此为止了。
我们总结一下:
Bind 方法不仅可以智能的创建快捷方式,还可以封装闭包函数,并把所有的对应绑定都存入到 bindings 数组中,如果一旦某个对象解析过了依然调用 bind 方法,那么就会 rebound 反弹,通过监听者的回调函数更新对象。
关于 LearnKu
推荐文章: