参考资料:
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);
}