/**
* 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方法(四)的更多相关文章

  1. Laravel (5.5.33) 加载过程---instance方法(二)

    在bootstrap/app.php /** * 对于其中的instance register singleton 方法到时候单独拎出来说明 * * 1.设置基础路径 * 2.使用instance 方 ...

  2. Laravel (5.5.33) 加载过程(一)

    说明:  由于公司项目使用Laravel 框架  也是第一次接触此框架  作为一个新手 记录使用过程的一些事情  以及对于框架源码分析的记录  整理自己的思路 也希望对大家有帮助  如果那里不对的地方 ...

  3. Laravel (5.5.33) 加载过程(二)

    本次说明代码 /* |-------------------------------------------------------------------------- | Turn On The ...

  4. js实现动态加载脚本的方法实例汇总

      本文实例讲述了js实现动态加载脚本的方法.分享给大家供大家参考,具体如下: 最近公司的前端地图产品需要做一下模块划分,希望用户用到哪一块的功能再加载哪一块的模块,这样可以提高用户体验. 所以到处查 ...

  5. 重温.NET下Assembly的加载过程 ASP.NET Core Web API下事件驱动型架构的实现(三):基于RabbitMQ的事件总线

    重温.NET下Assembly的加载过程   最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程.虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后 ...

  6. 工厂模式模拟Spring的bean加载过程

    一.前言    在日常的开发过程,经常使用或碰到的设计模式有代理.工厂.单例.反射模式等等.下面就对工厂模式模拟spring的bean加载过程进行解析,如果对工厂模式不熟悉的,具体可以先去学习一下工厂 ...

  7. linux内核启动以及文件系统的加载过程

    Linux 内核启动及文件系统加载过程 当u-boot 开始执行 bootcmd 命令,就进入 Linux 内核启动阶段.普通 Linux 内核的启动过程也可以分为两个阶段.本文以项目中使用的 lin ...

  8. Inside Flask - flask 扩展加载过程

    Inside Flask - flask 扩展加载过程 flask 扩展(插件)通常是以 flask_<扩展名字> 为扩展的 python 包名,而使用时,可用 import flask. ...

  9. web.xml 的加载过程

    初始化过程: 在启动Web项目时,容器(比如Tomcat)会读web.xml配置文件中的两个节点<listener>和<contex-param>. 接着容器会创建一个Serv ...

随机推荐

  1. 在Eclipse中设置Maven插件

    [步骤] Maven插件的设置: ①installations:指定Maven核心程序的位置.不建议使用Maven插件自带的Maven程序,而应该使用我们自己解压的那个. ②user settings ...

  2. [luoguP2701] [USACO5.3]巨大的牛棚Big Barn(DP)

    传送门 经典问题. 找出最大的不包含 1 的正方形. f[i][j] 表示 以 (i,j) 结尾的最大的不包含 1 的正方形 f[i][j] = min(f[i - 1][j], f[i][j - 1 ...

  3. Servlet监听器(Listener)实例

    以下内容是翻译自http://www.journaldev.com/1945/servletcontextlistener-servlet-listener-example: 说明:web.xml的加 ...

  4. Java泛型解析(01):认识泛型

    Java泛型解析(01):认识泛型 What      Java从1.0版本号到如今的8.中间Java5中发生了一个非常重要的变化,那就是泛型机制的引入.Java5引入了泛型,主要还是为了满足在199 ...

  5. ios 使用第三方框架注意

    在ios中使用第三方类库        在项目开发中经常会用到一些第三方类库,通常有两种方法来做到:一种方法是直接把所有的.h和.m文件复制到项目中:另一种方法是把.xcodeproj拖到项目中生成静 ...

  6. javaScript 检測 能否够连接指定server

    本文主要讲述怎样在js里面从多个服务端servlet中找到可用的地址 一般项目部署到生产环境之后会有一个生产网段(就是你能够在家訪问)和一个办公网段(仅仅能在公司才干訪问). 我们的项目部署好了之后, ...

  7. 【Eclipse提高开发速度-插件篇】安装VJET插件,JS等提示开发插件

    1.安装Apache Batik CSS 一般安装VJET插件会出现 Cannot complete the install because one or more required items co ...

  8. how to use webpart container in kentico

    https://docs.kentico.com/k11/developing-websites/developing-websites-using-the-portal-engine/using-w ...

  9. git diff比较使用

    git diff 等同于 git diff HEAD jiqing@ubuntu:/home/wwwroot/default/siemens/new_hotel$ git diff HEAD diff ...

  10. [模板]平衡树splay

    气死我了,调了一个下午+两节课,各种大大小小的错误,各种调QAQ,最后总之是调出来了. 其实就是一个双旋操作,然后其他就是左儿子<当前节点<右儿子,剩下就是细节了. 题干: 题目描述 您需 ...