nce属性中,分别起了app和Container两个名字。将vendor路径与bootstrap/cache/packages.php里的providers服务提供者路径传入PackageManifest类中,并绑定在了app对象的instance中,大家在这个方法后dd($this)会发现跟setBasePath一样,instance属性中多了几条,只是其中三个是对象而已。
registerBaseServiceProviders:注册了基本的providers,event事件服务提供者、log日志服务提供者、routing路由部分服务提供者。服务提供者的部分会在后面解释,现在把它看做是一个功能模块的入口就可以了。同样的,我们在这个方法后面dd($this)会发先serviceProviders属性与loadedProviders属性增加了对应的值。bindings属性也增加了provider相应的boot闭包,闭包中存储的是实例化对象的代码,运行后会得到一个对象实例,以闭包的形式存储来实现按需加载。
registerCoreContainerAliases:跟它的名字说的一样,只是注册了容器的核心类别名,同样打印后发现在aliases、abstractAliases属性中增加了相应的映射数组。以后会根据这个别名来方便的实例化对象,这个列表太长我就不放图了
好的,总结一下,application类初始化的时候它做了这么些工作:
1、设置路径 2、绑定了app对象和packages包的实例 3、注册了基本服务提供者 4、增加了核心类的别名 全都是一些配置工作。
好,回到app.php文件,$app执行了三个singleton方法,通过注释我们可以知道它绑定了一些重要的接口道容器中。我们点击跳转后一路跟踪到G:\wamp64\www\test\laravel55\vendor\laravel\framework\src\Illuminate\Container\Container.php文件的bind方法中看着很长的代码,其实都是状态判断,这个函数所做的事情还是讲传入的类名路径转换为一个启动服务的闭包,并保存在容器的bindings属性中。见下方代码,getClosure方法也可以看一下,比较简单。
1 public function bind($abstract, $concrete = null, $shared = false)
2 {
3 //抽象类型判断
4 $this->dropStaleInstances($abstract);
5
6 if (is_null($concrete)) {
7 $concrete = $abstract;
8 }
9
10 //这一阶段重点,刚刚我们index传入的类路径不是闭包,就会在这里被getClosure方法转换成一个返回对象实例的闭包了
11 if (! $concrete instanceof Closure) {
12 $concrete = $this->getClosure($abstract, $concrete);
13 }
14 //将闭包绑定在bindings属性中
15 $this->bindings[$abstract] = compact('concrete', 'shared');
16
17 // If the abstract type was already resolved in this container we'll fire the
18 // rebound listener so that any objects which have already gotten resolved
19 // can have their copy of the object updated via the listener callbacks.
20 if ($this->resolved($abstract)) {
21 $this->rebound($abstract);
22 }
23 }
我们在app.php文件的singleton之后再次dd($app)会发现bindings属性中多出了几个相应的属性,见下图,其中http\kernel用来处理http请求,console\kernel用来处理artisan命令行请求,debug\exceptionHandler便是处理异常错误的了。
app.php文件看完了,我们再回到index.php文件,第四行laravel制造了一个kernel实例,还记得刚刚在app.php文件时,我们通过singleton绑定的那个闭包函数吗?这里马上就派上用场了,make顾名思义就制造,这个方法通过类名路径或别名返回一个对象实例(对,还记得刚刚application对象构造函数绑定了一大堆别名吗)。G:\wamp64\www\test\laravel55\vendor\laravel\framework\src\Illuminate\Foundation\Application.php类的make方法
1 public function make($abstract, array $parameters = [])
2 {
3 //这里获取了传入类的别名,getAlias方法通过递归取出存储在容器中的别名,不过现在kernel没有别名所以还是刚刚传入的类路径
4 $abstract = $this->getAlias($abstract);
5 //也不是延迟加载服务直接跳转到父类make方法
6 if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
7 $this->loadDeferredProvider($abstract);
8 }
9
10 return parent::make($abstract, $parameters);
11 }
G:\wamp64\www\test\laravel55\vendor\laravel\framework\src\Illuminate\Container\Container.php在container类的make方法就开始从容器中解析类了,一开始那一大段都是检测上下文绑定的,这个属于契约接口的动态调用,暂时可以不去看它,重点在于从getConcrete方法获取到闭包后,直接进入了build构建方法。
public function make($abstract, array $parameters = [])
{
return $this->resolve($abstract, $parameters);
}
protected function resolve($abstract, $parameters = [])
{
$abstract = $this->getAlias($abstract);
//是否存在构建上下文,此出为了服务提供者的契约
$needsCon