参考资料:
php:laravel底层外围代码剖析之make办法的实现
Laravel加载过程---make办法
实例化Illuminate\Contracts\Http\Kernel
make办法
/public/index.php
$app = require_once __DIR__.'/../bootstrap/app.php';$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$app->make() => 父类Application中的make() => resolve()办法
resolve办法
vendor/laravel/framework/src/Illuminate/Container/Container.php
/** * 第一次调用 * $abstract Illuminate\Contracts\Http\Kernel::class * $concrete 匿名函数 * * 第二次调用 * $abstract 'App\Http\Kernel' * $concrete 'App\Http\Kernel' (getConcrete办法返回) * 执行build()办法获取App\Http\Kernel的实例化对象,返回给getClosure() */protected function resolve($abstract, $parameters = [], $raiseEvents = true){ ... //依据$abstract从bindings数组中获取$concrete匿名函数 $concrete = $this->getConcrete($abstract); //判断$concrete和$abstract是否雷同,或者$concrete是一个匿名函数 if ($this->isBuildable($concrete, $abstract)) { //实例化$concrete的类 $object = $this->build($concrete); } else { //递归执行make $object = $this->make($concrete); } ... }
getClosure()办法递归调用
/** * 第一次调用 * $abstract 'Illuminate\Contracts\Http\Kernel' * $concrete 'App\Http\Kernel' * * 第二次调用 * 获取App\Http\Kernel的实例,向上返回给build()办法 */protected function getClosure($abstract, $concrete){ return function ($container, $parameters = []) use ($abstract, $concrete) { if ($abstract == $concrete) { return $container->build($concrete); } return $container->resolve($concrete, $parameters, $raiseEvents = false); };}
build办法
vendor/laravel/framework/src/Illuminate/Container/Container.php
/** * 第一次调用 * $concrete 匿名函数 * * 第二次调用 * $concrete 'App\Http\Kernel' * 执行反射,获取App\Http\Kernel类的实例化对象 * 返回给resolve()办法 */public function build($concrete){ if ($concrete instanceof Closure) { //bind()办法中$concrete = $this->getClosure($abstract, $concrete); return $concrete($this, $this->getLastParameterOverride()); } $reflector = new ReflectionClass($concrete); if (! $reflector->isInstantiable()) { return $this->notInstantiable($concrete); } $this->buildStack[] = $concrete; $constructor = $reflector->getConstructor(); if (is_null($constructor)) { array_pop($this->buildStack); return new $concrete; } $dependencies = $constructor->getParameters(); $instances = $this->resolveDependencies( $dependencies ); array_pop($this->buildStack); return $reflector->newInstanceArgs($instances);}