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
反弹,通过监听者的回调函数更新对象。