Laravel (5.5.33) 加载过程---make方法(四)
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @return mixed
*/
public function make($abstract)
{
return $this->resolve($abstract);
}
make函数的大致执行流程
其中resolve源码的说明
/**
* Resolve the given type from the container.
*
* @param string $abstract
* @param array $parameters
* @return mixed
*/
protected function resolve($abstract, $parameters = [])
{
/**
* 别名转换
*/
$abstract = $this->getAlias($abstract); /**
* 如果参数不为空 或者给定的别名存在存在contextual中 则$needsContextualBuild 为true
*/
$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.
/**
* 如果是给定的别名是容器类别名
* 如果是application中的 $this->instance('app', $this) 时候instances数组中不存在 app
* app container 并且不需要build 则返回容器
*/
if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
return $this->instances[$abstract];
} /**
* 保存参数到with数组中
*/
$this->with[] = $parameters; /**
* 如果contextual 中存在别名信息 返回对于信息的值
* 如果bindings 中存在别名信息 返回对于信息中的concrete键的值
* 如果上述都不成立 返回别名
*/
$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.
/**
* 如果$concrete 和$abstract相同 或者$concrete是一个匿名函数 条件成立
*/
if ($this->isBuildable($concrete, $abstract)) {
/**
* 实例化$concrete 代码的类
*/
$object = $this->build($concrete);
} else {
/**
* 重新执行make函数
*/
$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.
/**
* 获取extenders 中注册该别名对于的方法数组 逐个执行
*/
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.
/**
* 判断bindings或者instances中是否已经存在该别名信息 判断$needsContextualBuild值
*/
if ($this->isShared($abstract) && ! $needsContextualBuild) {
$this->instances[$abstract] = $object;
} /**
* 执行全局注册的函数事件globalResolvingCallbacks 该函数注册的事件 resolvingCallbacks
* 完成实例化调用的全局事件globalAfterResolvingCallbacks 已经改函数实例化完成后调用的事件afterResolvingCallbacks
*/
$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;
}
其中关键的实例化返回build函数说明
/**
* 实例化一个对象
* @param unknown $concrete
* @return unknown|void|object
*/
public function build($concrete)
{
// If the concrete type is actually a Closure, we will just execute it and
// hand back the results of the functions, which allows functions to be
// used as resolvers for more fine-tuned resolution of these objects.
/**
* 如果是匿名函数
*/
if ($concrete instanceof Closure) {
return $concrete($this, $this->getLastParameterOverride());
} /**
* @link http://php.net/manual/zh/reflectionclass.construct.php
* @return ReflectionClass $reflector
*/
$reflector = new ReflectionClass($concrete); // If the type is not instantiable, the developer is attempting to resolve
// an abstract type such as an Interface of Abstract Class and there is
// no binding registered for the abstractions so we need to bail out.
/**
* @link http://php.net/manual/zh/reflectionclass.isinstantiable.php
* 检查这个类是否可实例化 如果不能实例化 报错
*/
if (! $reflector->isInstantiable()) {
return $this->notInstantiable($concrete);
} /**
* 添加记录
*/
$this->buildStack[] = $concrete; /**
* 获取已反射的类的构造函数
* @link http://php.net/manual/zh/reflectionclass.getconstructor.php
* @return ReflectionMethod $constructor
*/
$constructor = $reflector->getConstructor(); // If there are no constructors, that means there are no dependencies then
// we can just resolve the instances of the objects right away, without
// resolving any other types or dependencies out of these containers.
/**
* 获取失败 弹出buildStack数据 返回一个实力
*/
if (is_null($constructor)) {
array_pop($this->buildStack); return new $concrete;
} /**
* 通过 ReflectionParameter 数组返回参数列表
* @link http://php.net/manual/zh/reflectionfunctionabstract.getparameters.php
* @var ReflectionParameter $dependencies
*/
$dependencies = $constructor->getParameters(); // Once we have all the constructor's parameters we can create each of the
// dependency instances and then use the reflection instances to make a
// new instance of this class, injecting the created dependencies in.
/**
* 返回类中的属性和对应的值
* @var array $instances
*/
$instances = $this->resolveDependencies(
$dependencies
); /**
* 弹出buildStack数据
*/
array_pop($this->buildStack); /**
* @link http://php.net/manual/zh/reflectionclass.newinstanceargs.php
* 创建一个类的新实例,给出的参数将传递到类的构造函数
*
* 给类中的属性赋值
*/
return $reflector->newInstanceArgs($instances);
}
通过resolveDependencies 获取类中属性的默认值 通过如果属性是一个匿名函数 则执行匿名函数 如果是一个类 值实例化类
/**
* 返回对于属性的值
* @param array $dependencies
* @return mixed[]|\Closure[]|unknown[]
*/
protected function resolveDependencies(array $dependencies)
{
$results = []; /**
* @var ReflectionParameter $dependency
*/
foreach ($dependencies as $dependency) {
// If this dependency has a override for this particular build we will use
// that instead as the value. Otherwise, we will continue with this run
// of resolutions and let reflection attempt to determine the result.
if ($this->hasParameterOverride($dependency)) {
$results[] = $this->getParameterOverride($dependency); continue;
} // If the class is null, it means the dependency is a string or some other
// primitive type which we can not resolve since it is not a class and
// we will just bomb out with an error since we have no-where to go.
/**
* @link http://php.net/manual/zh/reflectionparameter.getclass.php
* @var ReflectionClass $class
*
* 若该参数为对象,返回该对象的类名
* 如果不是一点对象 使用 resolvePrimitive方法
* 如果是一个对象对象信息 创建一个该对象 解决依赖问题
*/
$results[] = is_null($class = $dependency->getClass())
? $this->resolvePrimitive($dependency)
: $this->resolveClass($dependency);
} return $results;
}
如果是一个配置的匿名函数 则通过resolvePrimitive返回执行该匿名函数 返回
/**
* 如果是一个匿名对象 执行匿名对象 返回执行结果
* 如果是一个默认值 则返回默认值
* 如果不存在默认值 则报错
*/
protected function resolvePrimitive(ReflectionParameter $parameter)
{
/**查询给定的别名 查询contextual 中是否存在信息 如果存在返回 如果是抽象类别名 游离抽象类数组 查询对于的别名是否存在contextual 中 存在返回
* 如果是一个匿名函数 值执行匿名函数 返回结果 如果不是你们函数 返回contextual中对于的值
*/
if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
return $concrete instanceof Closure ? $concrete($this) : $concrete;
} /**
* @link http://php.net/manual/zh/reflectionparameter.isdefaultvalueavailable.php
* 查看是否存在默认值
*/
if ($parameter->isDefaultValueAvailable()) {
return $parameter->getDefaultValue();
} /**
* 报错
*/
$this->unresolvablePrimitive($parameter);
}
如果该属性是一个类 则执行resolveClass 实例化该类
/**
* 实例化对于的类
* @param ReflectionParameter $parameter
* @throws BindingResolutionException
* @return mixed|unknown|mixed
*/
protected function resolveClass(ReflectionParameter $parameter)
{
try {
/**
* 实例化类
*/
return $this->make($parameter->getClass()->name);
} // If we can not resolve the class instance, we will check to see if the value
// is optional, and if it is we will return the optional parameter value as
// the value of the dependency, similarly to how we do this with scalars.
catch (BindingResolutionException $e) {
if ($parameter->isOptional()) {
return $parameter->getDefaultValue();
} throw $e;
}
}
Laravel (5.5.33) 加载过程---make方法(四)的更多相关文章
- Laravel (5.5.33) 加载过程---instance方法(二)
在bootstrap/app.php /** * 对于其中的instance register singleton 方法到时候单独拎出来说明 * * 1.设置基础路径 * 2.使用instance 方 ...
- Laravel (5.5.33) 加载过程(一)
说明: 由于公司项目使用Laravel 框架 也是第一次接触此框架 作为一个新手 记录使用过程的一些事情 以及对于框架源码分析的记录 整理自己的思路 也希望对大家有帮助 如果那里不对的地方 ...
- Laravel (5.5.33) 加载过程(二)
本次说明代码 /* |-------------------------------------------------------------------------- | Turn On The ...
- js实现动态加载脚本的方法实例汇总
本文实例讲述了js实现动态加载脚本的方法.分享给大家供大家参考,具体如下: 最近公司的前端地图产品需要做一下模块划分,希望用户用到哪一块的功能再加载哪一块的模块,这样可以提高用户体验. 所以到处查 ...
- 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线
重温.NET下Assembly的加载过程 最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...
- 工厂模式模拟Spring的bean加载过程
一.前言 在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...
- linux内核启动以及文件系统的加载过程
Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...
- Inside Flask - flask 扩展加载过程
Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ...
- web.xml 的加载过程
初始化过程: 在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>. 接着容器会创建一个Serv ...
随机推荐
- 【OpenCV, MFC, DIP】向图像中加入各种噪声
1.椒盐噪声 Mat dstImage = srcImage.clone(); ; k < n; k++) { //随机取值行列 int i = rand() % dstImage.rows; ...
- Java Web学习总结(31)——全站HTTPS化SSL免费证书使用
1 背景 谷歌从 2017 年起,Chrome 浏览器将也会把采用 HTTP 协议的网站标记为「不安全」网站:苹果从 2017 年 iOS App 将强制使用 HTTPS:在国内热火朝天的小程序也要求 ...
- 九度oj 题目1059:abc
题目1059:abc 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:4510 解决:3546 题目描述: 设a.b.c均是0到9之间的数字,abc.bcc是两个三位数,且有:abc+bcc ...
- poj 3253 Fence Repair(priority_queue)
Fence Repair Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 40465 Accepted: 13229 De ...
- spring-quartz定时器简单用法
基本配置: 1.quartz.properties #============================================================== #Configure ...
- [codevs 1482]路线统计(矩阵乘法)
题目:http://codevs.cn/problem/1482/ 分析:很像“经过K条边的最短路径条数”.但有所不同,那就是不是边数固定,而是路径总长度固定.看似不能用矩阵乘法了……但注意到每条边的 ...
- 1010 过河卒 2002年NOIP全国联赛普及组codevs
1010 过河卒 2002年NOIP全国联赛普及组codevs 题目描述 Description 如图,A 点有一个过河卒,需要走到目标 B 点.卒行走规则:可以向下.或者向右.同时在棋盘上的任一点 ...
- Eclipse Java Build Path详解
Eclipse Java Build Path详解 1.设置"source folder"与"output folder". * source folder:存 ...
- MVC WebApi 将返回值改为JSON格式
新增一个类: public class BrowserJsonFormatter : JsonMediaTypeFormatter { public BrowserJsonFormatter() { ...
- symfony2笔记
路由可以在全局定义,也可以在单个bundle内部定义 全局定义:app/config/routing.yml 局部bundle定义:src/Miyaye/webBundle/Resources/con ...