1. /**
  2. * Resolve the given type from the container.
  3. *
  4. * @param string $abstract
  5. * @return mixed
  6. */
  7. public function make($abstract)
  8. {
  9. return $this->resolve($abstract);
  10. }

make函数的大致执行流程


其中resolve源码的说明

  1. /**
  2. * Resolve the given type from the container.
  3. *
  4. * @param string $abstract
  5. * @param array $parameters
  6. * @return mixed
  7. */
  8. protected function resolve($abstract, $parameters = [])
  9. {
  10. /**
  11. * 别名转换
  12. */
  13. $abstract = $this->getAlias($abstract);
  14.  
  15. /**
  16. * 如果参数不为空 或者给定的别名存在存在contextual中 则$needsContextualBuild 为true
  17. */
  18. $needsContextualBuild = ! empty($parameters) || ! is_null(
  19. $this->getContextualConcrete($abstract)
  20. );
  21.  
  22. // If an instance of the type is currently being managed as a singleton we'll
  23. // just return an existing instance instead of instantiating new instances
  24. // so the developer can keep using the same objects instance every time.
  25. /**
  26. * 如果是给定的别名是容器类别名
  27. * 如果是application中的 $this->instance('app', $this) 时候instances数组中不存在 app
  28. * app container 并且不需要build 则返回容器
  29. */
  30. if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
  31. return $this->instances[$abstract];
  32. }
  33.  
  34. /**
  35. * 保存参数到with数组中
  36. */
  37. $this->with[] = $parameters;
  38.  
  39. /**
  40. * 如果contextual 中存在别名信息 返回对于信息的值
  41. * 如果bindings 中存在别名信息 返回对于信息中的concrete键的值
  42. * 如果上述都不成立 返回别名
  43. */
  44. $concrete = $this->getConcrete($abstract);
  45.  
  46. // We're ready to instantiate an instance of the concrete type registered for
  47. // the binding. This will instantiate the types, as well as resolve any of
  48. // its "nested" dependencies recursively until all have gotten resolved.
  49. /**
  50. * 如果$concrete 和$abstract相同 或者$concrete是一个匿名函数 条件成立
  51. */
  52. if ($this->isBuildable($concrete, $abstract)) {
  53. /**
  54. * 实例化$concrete 代码的类
  55. */
  56. $object = $this->build($concrete);
  57. } else {
  58. /**
  59. * 重新执行make函数
  60. */
  61. $object = $this->make($concrete);
  62. }
  63.  
  64. // If we defined any extenders for this type, we'll need to spin through them
  65. // and apply them to the object being built. This allows for the extension
  66. // of services, such as changing configuration or decorating the object.
  67. /**
  68. * 获取extenders 中注册该别名对于的方法数组 逐个执行
  69. */
  70. foreach ($this->getExtenders($abstract) as $extender) {
  71. $object = $extender($object, $this);
  72. }
  73.  
  74. // If the requested type is registered as a singleton we'll want to cache off
  75. // the instances in "memory" so we can return it later without creating an
  76. // entirely new instance of an object on each subsequent request for it.
  77. /**
  78. * 判断bindings或者instances中是否已经存在该别名信息 判断$needsContextualBuild值
  79. */
  80. if ($this->isShared($abstract) && ! $needsContextualBuild) {
  81. $this->instances[$abstract] = $object;
  82. }
  83.  
  84. /**
  85. * 执行全局注册的函数事件globalResolvingCallbacks 该函数注册的事件 resolvingCallbacks
  86. * 完成实例化调用的全局事件globalAfterResolvingCallbacks 已经改函数实例化完成后调用的事件afterResolvingCallbacks
  87. */
  88. $this->fireResolvingCallbacks($abstract, $object);
  89.  
  90. // Before returning, we will also set the resolved flag to "true" and pop off
  91. // the parameter overrides for this build. After those two things are done
  92. // we will be ready to return back the fully constructed class instance.
  93. $this->resolved[$abstract] = true;
  94.  
  95. array_pop($this->with);
  96.  
  97. return $object;
  98. }

其中关键的实例化返回build函数说明

  1. /**
  2. * 实例化一个对象
  3. * @param unknown $concrete
  4. * @return unknown|void|object
  5. */
  6. public function build($concrete)
  7. {
  8. // If the concrete type is actually a Closure, we will just execute it and
  9. // hand back the results of the functions, which allows functions to be
  10. // used as resolvers for more fine-tuned resolution of these objects.
  11. /**
  12. * 如果是匿名函数
  13. */
  14. if ($concrete instanceof Closure) {
  15. return $concrete($this, $this->getLastParameterOverride());
  16. }
  17.  
  18. /**
  19. * @link http://php.net/manual/zh/reflectionclass.construct.php
  20. * @return ReflectionClass $reflector
  21. */
  22. $reflector = new ReflectionClass($concrete);
  23.  
  24. // If the type is not instantiable, the developer is attempting to resolve
  25. // an abstract type such as an Interface of Abstract Class and there is
  26. // no binding registered for the abstractions so we need to bail out.
  27. /**
  28. * @link http://php.net/manual/zh/reflectionclass.isinstantiable.php
  29. * 检查这个类是否可实例化 如果不能实例化 报错
  30. */
  31. if (! $reflector->isInstantiable()) {
  32. return $this->notInstantiable($concrete);
  33. }
  34.  
  35. /**
  36. * 添加记录
  37. */
  38. $this->buildStack[] = $concrete;
  39.  
  40. /**
  41. * 获取已反射的类的构造函数
  42. * @link http://php.net/manual/zh/reflectionclass.getconstructor.php
  43. * @return ReflectionMethod $constructor
  44. */
  45. $constructor = $reflector->getConstructor();
  46.  
  47. // If there are no constructors, that means there are no dependencies then
  48. // we can just resolve the instances of the objects right away, without
  49. // resolving any other types or dependencies out of these containers.
  50. /**
  51. * 获取失败 弹出buildStack数据 返回一个实力
  52. */
  53. if (is_null($constructor)) {
  54. array_pop($this->buildStack);
  55.  
  56. return new $concrete;
  57. }
  58.  
  59. /**
  60. * 通过 ReflectionParameter 数组返回参数列表
  61. * @link http://php.net/manual/zh/reflectionfunctionabstract.getparameters.php
  62. * @var ReflectionParameter $dependencies
  63. */
  64. $dependencies = $constructor->getParameters();
  65.  
  66. // Once we have all the constructor's parameters we can create each of the
  67. // dependency instances and then use the reflection instances to make a
  68. // new instance of this class, injecting the created dependencies in.
  69. /**
  70. * 返回类中的属性和对应的值
  71. * @var array $instances
  72. */
  73. $instances = $this->resolveDependencies(
  74. $dependencies
  75. );
  76.  
  77. /**
  78. * 弹出buildStack数据
  79. */
  80. array_pop($this->buildStack);
  81.  
  82. /**
  83. * @link http://php.net/manual/zh/reflectionclass.newinstanceargs.php
  84. * 创建一个类的新实例,给出的参数将传递到类的构造函数
  85. *
  86. * 给类中的属性赋值
  87. */
  88. return $reflector->newInstanceArgs($instances);
  89. }

通过resolveDependencies 获取类中属性的默认值  通过如果属性是一个匿名函数 则执行匿名函数  如果是一个类  值实例化类

  1. /**
  2. * 返回对于属性的值
  3. * @param array $dependencies
  4. * @return mixed[]|\Closure[]|unknown[]
  5. */
  6. protected function resolveDependencies(array $dependencies)
  7. {
  8. $results = [];
  9.  
  10. /**
  11. * @var ReflectionParameter $dependency
  12. */
  13. foreach ($dependencies as $dependency) {
  14. // If this dependency has a override for this particular build we will use
  15. // that instead as the value. Otherwise, we will continue with this run
  16. // of resolutions and let reflection attempt to determine the result.
  17. if ($this->hasParameterOverride($dependency)) {
  18. $results[] = $this->getParameterOverride($dependency);
  19.  
  20. continue;
  21. }
  22.  
  23. // If the class is null, it means the dependency is a string or some other
  24. // primitive type which we can not resolve since it is not a class and
  25. // we will just bomb out with an error since we have no-where to go.
  26. /**
  27. * @link http://php.net/manual/zh/reflectionparameter.getclass.php
  28. * @var ReflectionClass $class
  29. *
  30. * 若该参数为对象,返回该对象的类名
  31. * 如果不是一点对象 使用 resolvePrimitive方法
  32. * 如果是一个对象对象信息 创建一个该对象 解决依赖问题
  33. */
  34. $results[] = is_null($class = $dependency->getClass())
  35. ? $this->resolvePrimitive($dependency)
  36. : $this->resolveClass($dependency);
  37. }
  38.  
  39. return $results;
  40. }

如果是一个配置的匿名函数  则通过resolvePrimitive返回执行该匿名函数  返回

  1. /**
  2. * 如果是一个匿名对象 执行匿名对象 返回执行结果
  3. * 如果是一个默认值 则返回默认值
  4. * 如果不存在默认值 则报错
  5. */
  6. protected function resolvePrimitive(ReflectionParameter $parameter)
  7. {
  8. /**查询给定的别名 查询contextual 中是否存在信息 如果存在返回 如果是抽象类别名 游离抽象类数组 查询对于的别名是否存在contextual 中 存在返回
  9. * 如果是一个匿名函数 值执行匿名函数 返回结果 如果不是你们函数 返回contextual中对于的值
  10. */
  11. if (! is_null($concrete = $this->getContextualConcrete('$'.$parameter->name))) {
  12. return $concrete instanceof Closure ? $concrete($this) : $concrete;
  13. }
  14.  
  15. /**
  16. * @link http://php.net/manual/zh/reflectionparameter.isdefaultvalueavailable.php
  17. * 查看是否存在默认值
  18. */
  19. if ($parameter->isDefaultValueAvailable()) {
  20. return $parameter->getDefaultValue();
  21. }
  22.  
  23. /**
  24. * 报错
  25. */
  26. $this->unresolvablePrimitive($parameter);
  27. }

如果该属性是一个类  则执行resolveClass 实例化该类

  1. /**
  2. * 实例化对于的类
  3. * @param ReflectionParameter $parameter
  4. * @throws BindingResolutionException
  5. * @return mixed|unknown|mixed
  6. */
  7. protected function resolveClass(ReflectionParameter $parameter)
  8. {
  9. try {
  10. /**
  11. * 实例化类
  12. */
  13. return $this->make($parameter->getClass()->name);
  14. }
  15.  
  16. // If we can not resolve the class instance, we will check to see if the value
  17. // is optional, and if it is we will return the optional parameter value as
  18. // the value of the dependency, similarly to how we do this with scalars.
  19. catch (BindingResolutionException $e) {
  20. if ($parameter->isOptional()) {
  21. return $parameter->getDefaultValue();
  22. }
  23.  
  24. throw $e;
  25. }
  26. }

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. 【Codeforces 584D】Dima and Lisa

    [链接] 我是链接,点我呀:) [题意] 让你把一个奇数n分成最多个质数的和 [题解] 10的9次方以内,任意两个质数之间的差距最大为300 因此可以这样,我们先从i=n-2开始一直递减直到i变成最大 ...

  2. 关于${ctx}拿不到值的问题

    当项目开发时我们喜欢用 <c:set var="ctx" value="${pageContext.request.contextPath}"/>来 ...

  3. 洛谷—— P2196 挖地雷

    https://www.luogu.org/problem/show?pid=2196 题目背景 NOIp1996提高组第三题 题目描述 在一个地图上有N个地窖(N<=20),每个地窖中埋有一定 ...

  4. cogs——1578. 次小生成树初级练习题

    1578. 次小生成树初级练习题 ☆   输入文件:mst2.in   输出文件:mst2.out   简单对比时间限制:1 s   内存限制:256 MB [题目描述] 求严格次小生成树 [输入格式 ...

  5. 16、Java并发性和多线程-死锁

    以下内容转自http://ifeve.com/deadlock/: 死锁是两个或更多线程阻塞着等待其它处于死锁状态的线程所持有的锁.死锁通常发生在多个线程同时但以不同的顺序请求同一组锁的时候. 例如, ...

  6. maven bug之Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:2.5.1:compile (default-compile) on project acSpaceCommon: Fatal error compiling: tools.jar not found: C:\Program Files\J

    maven打包项目的时候一直报这个异常  一般的解决办法我都试过 在pom.xml加代码 也不行  只有10分了  求大神解答 这是因为测试代码时遇到错误,它会停止编译.只需要在pom.xml的< ...

  7. OpenCV基础篇之像素操作对照度调节

    程序及分析 /* * FileName : contrast.cpp * Author : xiahouzuoxin @163.com * Version : v1.0 * Date : Tue 29 ...

  8. [学习笔记]JavaScript基础

    JavaScript概述 1. JavaScript定义 JavaScript是Netscape公司开发的一种基于对象和事件驱动的脚本语言.它是弱类型语言.仅仅能由浏览器解释运行. 当中: 脚本语言: ...

  9. Go/Python/Erlang编程语言对比分析及示例 基于RabbitMQ.Client组件实现RabbitMQ可复用的 ConnectionPool(连接池) 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil 分享基于MemoryCache(内存缓存)的缓存工具类,C# B/S 、C/S项目均可以使用!

    Go/Python/Erlang编程语言对比分析及示例   本文主要是介绍Go,从语言对比分析的角度切入.之所以选择与Python.Erlang对比,是因为做为高级语言,它们语言特性上有较大的相似性, ...

  10. WingIDE 5.0注冊机

    在wingIDE下开发python很方便,但IDE不是免费的,网上有破解的方法.请支持正版. 把下列文件CalcActivationCode.py载入到wingIDE中.LicenseID能够随便给一 ...