源码阅读 Application : make
// 1) Alias 解析
$abstract = $this->getAlias($abstract);
// 2) 如果是延迟加载且尚未实例化
if (isset($this->deferredServices[$abstract]) && ! isset($this->instances[$abstract])) {
$this->loadDeferredProvider($abstract);
}
// 3) parent::make
return parent::make($abstract, $parameters);1) Alias 解析
getAlias
php
// aliases sample
/* $this->aliases = [
[Illuminate\Foundation\Application] => app
[Illuminate\Contracts\Container\Container] => app
[Illuminate\Contracts\Foundation\Application] => app
[Psr\Container\ContainerInterface] => app
[Illuminate\Auth\AuthManager] => auth
[Illuminate\Contracts\Auth\Factory] => auth
...
]
*/
// 如果未设置
// 返回 Illuminate\Foundation\Application
if (! isset($this->aliases[$abstract])) {
return $abstract;
}
if ($this->aliases[$abstract] === $abstract) {
throw new LogicException("[{$abstract}] is aliased to itself.");
}
return $this->getAlias($this->aliases[$abstract]);2) 延迟加载 Provider (loadDeferredProvider())
php
// aliases sample
/* $this->deferredServices = [
[Illuminate\Bus\Dispatcher] => Illuminate\Bus\BusServiceProvider
[Illuminate\Contracts\Bus\Dispatcher] => Illuminate\Bus\BusServiceProvider
[Illuminate\Contracts\Bus\QueueingDispatcher] => Illuminate\Bus\BusServiceProvider
[cache] => Illuminate\Cache\CacheServiceProvider
[cache.store] => Illuminate\Cache\CacheServiceProvider
[memcached.connector] => Illuminate\Cache\CacheServiceProvider
...
]
*/
if (! isset($this->deferredServices[$service])) {
return;
}
$provider = $this->deferredServices[$service];
// 如果 service provider 尚未加载, 我们可以加载这个服务, 然后从这个列表中移除
if (! isset($this->loadedProviders[$provider])) {
// 1) 注册延迟加载的服务提供者
$this->registerDeferredProvider($provider, $service);
}2-1) 注册延迟加载的服务提供者
php
// 已经注册, 我们会把这个东西从列表中移除
if ($service) {
unset($this->deferredServices[$service]);
}
$this->register($instance = new $provider($this));
if (! $this->booted) {
$this->booting(function () use ($instance) {
$this->bootProvider($instance);
});
}3) parent::make 来创建应用
来源创建值
$abstract = Illuminate\Contracts\Http\Kernel::class函数解析
php
// 获取关联
$abstract = $this->getAlias($abstract);
$needsContextualBuild = ! empty($parameters) || ! is_null(
$this->getContextualConcrete($abstract)
);
// 如果是单例, 我们只需要返回唯一的实例, 不需要重新创建. 保证开发者使用同一个实例
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
}
$this->with[] = $parameters;
// 获取实例类型
$concrete = $this->getConcrete($abstract);
// 根据绑定来注册实例, 这个根据内部来加载到所有依赖
if ($this->isBuildable($concrete, $abstract)) {
// 1) build
$object = $this->build($concrete);
} else {
// 不可创建则视为存在, 则返回
$object = $this->make($concrete);
}
// 如果我们定义了扩展器, 我们必须应用这些修饰扩展
foreach ($this->getExtenders($abstract) as $extender) {
$object = $extender($object, $this);
}
// 如果注册为 singleton 模式 , 我们直接返回
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
}
// 触发回调
$this->fireResolvingCallbacks($abstract, $object);
// 在返回前, 需要标注标识, 并且移除 with 参数.
$this->resolved[$abstract] = true;
array_pop($this->with);
return $object;3-1) 使用 build 来创建对象
Illuminate/Container/Container::build(Illuminate::class)
php
// 如果实例类型是 闭包函数, 我们执行并且返回这些对象
// 这里的 app 应该是对应的 Application,
if ($concrete instanceof Closure) {
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);
// 根据给定的参数创建新实例(这就是传说中的自动注入(-WAIT-)?)
return $reflector->newInstanceArgs($instances);