摘抄自 :http://www.mamicode.com/info-detail-2231705.html](http://www.mamicode.com/info-detail-2231705.html
在laravel源码中index.php中,引入
$app = require_once __DIR__.'/../bootstrap/app.php';
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
其中这个make方法是从容器中解析一个实例 type return;其中Illuminate\Foundation\Application这个类和它的父类Illuminate\Container\Container类中都有make方法,
当执行index.php的时候,就会首先去执行Illuminate\Foundation\Application中的make方法
/**
2 * Resolve the given type from the container. 从容器当中解析给定的type
3 *
4 * (Overriding Container::make) 覆盖了父类中的make方法
5 *
6 * @param string $abstract 给定的type
7 * @param array $parameters 指定一些参数 可选项
8 * @return mixed
9 */
10 public function make($abstract, array $parameters = [])
11 {
12 $abstract = $this->getAlias($abstract);//调用父类中的getAlias方法
13 //如果在deferredServices这个数组设置了这个type并且在instances数组中没有设置这个type
14 if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
15 $this->loadDeferredProvider($abstract);//那么就执行这个方法:加载被定义为延迟的服务提供者
16 }
17
18 return parent::make($abstract, $parameters);//调用父类的make方法
19 }
好,我们一步一步的来,先看看这个getAlias方法,这个方法的作用就是返回这个类的别名,如果给出的是一个完整的类名且在aliases中已经设置了那么就返回这个类名的别名,如果没有设置过就返回这个类名本身,大家在看这个方法的时候可以先var_dump一下$app,对照着看里面的aliases数组,框架作者写这个方法真的很巧妙,至少这种递归方式在我实际开发当中很少用到。
/**
2 * Get the alias for an abstract if available.
3 *
4 * @param string $abstract
5 * @return string
6 *
7 * @throws \LogicException
8 */
9 public function getAlias($abstract)
10 {
11 if (! isset($this->aliases[$abstract])) {
12 return $abstract;
13 }
14
15 if ($this->aliases[$abstract] === $abstract) {
16 throw new LogicException("[{$abstract}] is aliased to itself.");
17 }
18
19 return $this->getAlias($this->aliases[$abstract]);
20 }
接下来就是对deferredServices和instances这个两个数组进行判断,在本例 app->make(Illuminate\Contracts\Http\Kernel::class); 当中,判断的结果为false,因此不执行loadDeferredProvider方法。
再接下来就是调用父类Illuminate\Container\Container中的make方法了
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function make($abstract, array $parameters = [])
{
return $this->resolve($abstract, $parameters);
}
重点来了,我们看看这个resolve方法执行了哪些操作,
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @param bool $raiseEvents
* @return mixed
*
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
protected function resolve($abstract, $parameters = [], $raiseEvents = true)
{
$abstract = $this->getAlias($abstract);
$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract)
);
// If an instance of the type is currently being managed as a singleton we'll
// just return an existing instance instead of instantiating new instances
// so the developer can keep using the same objects instance every time.
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
$this->with[] = $parameters;
$concrete = $this->getConcrete($abstract);
// We're ready to instantiate an instance of the concrete type registered for
// the binding. This will instantiate the types, as well as resolve any of
// its "nested" dependencies recursively until all have gotten resolved.
if ($this->isBuildable($concrete, $abstract)) {
$object = $this->build($concrete);
} else {
$object = $this->make($concrete);
}
// If we defined any extenders for this type, we'll need to spin through them
// and apply them to the object being built. This allows for the extension
// of services, such as changing configuration or decorating the object.
foreach ($this->getExtenders($abstract) as $extender) {
$object = $extender($object, $this);
}
// If the requested type is registered as a singleton we'll want to cache off
// the instances in "memory" so we can return it later without creating an
// entirely new instance of an object on each subsequent request for it.
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
}
if ($raiseEvents) {
$this->fireResolvingCallbacks($abstract, $object);
}
// Before returning, we will also set the resolved flag to "true" and pop off
// the parameter overrides for this build. After those two things are done
// we will be ready to return back the fully constructed class instance.
$this->resolved[$abstract] = true;
array_pop($this->with);
return $object;
}