Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用

 namespace yii\di;

 use Yii;
 use yii\base\InvalidConfigException;

 /**
  * Instance represents a reference to a named object in a dependency injection (DI) container or a service locator.
  * Instance 表示依赖注入容器或服务定位器中对某一个对象的引用
  *
  * You may use [[get()]] to obtain the actual object referenced by [[id]].
  * 可以通过使用[[get()]]方法和[[id]]获取实际对象的引用
  *
  * Instance is mainly used in two places:
  * Instance 主要在两个地方被使用:
  *
  * - When configuring a dependency injection container, you use Instance to reference a class name, interface name
  *   or alias name. The reference can later be resolved into the actual object by the container.
  *   在配置“依赖注入容器”时,可以使用Instance引用一个类名称、接口名称或别名。该引用将被容器将解析为实际的对象
  * - In classes which use service locator to obtain dependent objects.
  *   在类中使用服务定位器获取依赖对象时。
  *
  * The following example shows how to configure a DI container with Instance:
  *
  * ```php
  * $container = new \yii\di\Container;
  * $container->set('cache', 'yii\caching\DbCache', Instance::of('db'));
  * $container->set('db', [
  *     'class' => 'yii\db\Connection',
  *     'dsn' => 'sqlite:path/to/file.db',
  * ]);
  * ```
  *
  * And the following example shows how a class retrieves a component from a service locator:
  *
  * ```php
  * class DbCache extends Cache
  * {
  *     public $db = 'db';
  *
  *     public function init()
  *     {
  *         parent::init();
  *         $this->db = Instance::ensure($this->db, 'yii\db\Connection');
  *     }
  * }
  * ```
  *
  * @author Qiang Xue <qiang.xue@gmail.com>
  * @since 2.0
  */
 class Instance
 {
     /**
      * @var string the component ID, class name, interface name or alias name
      * @var string 用于保存类名、接口名或者别名
      */
     public $id;

     /**
      * Constructor.
      * 构造函数,仅将传入的ID赋值给 $id 属性
      * @param string $id the component ID
      */
     protected function __construct($id)
     {
         $this->id = $id;
     }

     /**
      * Creates a new Instance object.
      * 静态方法创建一个Instance实例
      * @param string $id the component ID
      * @return Instance the new Instance object.
      */
     public static function of($id)
     {
         return new static($id);//实例化访问该方法的类
     }

     /**
      * Resolves the specified reference into the actual object and makes sure it is of the specified type.
      * 静态方法,用于将引用解析成实际的对象,并确保这个对象的类型
      *
      * The reference may be specified as a string or an Instance object. If the former,
      * it will be treated as a component ID, a class/interface name or an alias, depending on the container type.
      *
      * If you do not specify a container, the method will first try `Yii::$app` followed by `Yii::$container`.
      *
      * For example,
      *
      * ```php
      * use yii\db\Connection;
      *
      * // returns Yii::$app->db
      * $db = Instance::ensure('db', Connection::className());
      * // returns an instance of Connection using the given configuration
      * $db = Instance::ensure(['dsn' => 'sqlite:path/to/my.db'], Connection::className());
      * ```
      *
      * @param object|string|array|static $reference an object or a reference to the desired object.
      * You may specify a reference in terms of a component ID or an Instance object.
      * Starting from version 2.0.2, you may also pass in a configuration array for creating the object.
      * If the "class" value is not specified in the configuration array, it will use the value of `$type`.
      * @param string $type the class/interface name to be checked. If null, type check will not be performed.
      * @param ServiceLocator|Container $container the container. This will be passed to [[get()]].
      * @return object the object referenced by the Instance, or `$reference` itself if it is an object.
      * @throws InvalidConfigException if the reference is invalid
      */
     public static function ensure($reference, $type = null, $container = null)
     {
         if (is_array($reference)) {//如果$reference是数组
             $class = isset($reference['class']) ? $reference['class'] : $type;//$reference中有类名,则将类名赋值给$class,否则将$type赋值给$class
             if (!$container instanceof Container) {//如果$container不是Container的实例
                 $container = Yii::$container;//则取Yii中定义的Container对象
             }
             unset($reference['class']);
             return $container->get($class, [], $reference);//返回引用的实例
         } elseif (empty($reference)) {//如果$reference为空,则抛出异常
             throw new InvalidConfigException('The required component is not specified.');
         }

         if (is_string($reference)) {//如果$reference是字符串
             $reference = new static($reference);//则实例化该引用类
         } elseif ($type === null || $reference instanceof $type) {//如果给定检查的类为空或者$reference是给定检查的类的实例
             return $reference;//返回该实例
         }

         if ($reference instanceof self) {//如果$reference是Istance的实例
             $component = $reference->get($container);//则获取调用$container的组件的对象
             if ($type === null || $component instanceof $type) {//如果给定检查的类为空或者$component是给定检查的类的实例
                 return $component;//返回$component
             } else {//否则抛出异常 跟预期的类型不符合
                 throw new InvalidConfigException('"' . $reference->id . '" refers to a ' . get_class($component) . " component. $type is expected.");
             }
         }

         $valueType = is_object($reference) ? get_class($reference) : gettype($reference);
         throw new InvalidConfigException("Invalid data type: $valueType. $type is expected.");
     }

     /**
      * Returns the actual object referenced by this Instance object.
      * 获取这个实例所引用的实际对象,它调用的是yii\di\Container::get()来获取实际对象
      * @param ServiceLocator|Container $container the container used to locate the referenced object.
      * If null, the method will first try `Yii::$app` then `Yii::$container`.
      * @return object the actual object referenced by this Instance object.
      */
     public function get($container = null)
     {
         if ($container) {
             return $container->get($this->id);//如果传入$container容器,则调用$container中的get方法获取引用的实际对象
         }
         if (Yii::$app && Yii::$app->has($this->id)) {//如果该对象已有实例
             return Yii::$app->get($this->id);//返回该实例
         } else {
             return Yii::$container->get($this->id);//否则调用yii\di\Container::get()来获取实际对象
         }
     }
 }

Yii源码阅读笔记(三十四)的更多相关文章

  1. Yii源码阅读笔记(十四)

    Model类,集中整个应用的数据和业务逻辑——场景.属性和标签: /** * Returns a list of scenarios and the corresponding active attr ...

  2. Yii源码阅读笔记(十八)

    View中的查找视图文件方法和渲染文件方法 /** * Finds the view file based on the given view name. * 通过view文件名查找view文件 * ...

  3. Yii源码阅读笔记(十六)

    Model类,集中整个应用的数据和业务逻辑—— /** * Generates a user friendly attribute label based on the give attribute ...

  4. Yii源码阅读笔记(十五)

    Model类,集中整个应用的数据和业务逻辑——验证 /** * Returns the attribute labels. * 返回属性的标签 * * Attribute labels are mai ...

  5. Yii源码阅读笔记(十二)

    Action类,控制器中方法的基类: namespace yii\base; use Yii; /** * Action is the base class for all controller ac ...

  6. Yii源码阅读笔记(十)

    控制器类,所有控制器的基类,用于调用模型和布局,输出到视图 namespace yii\base; use Yii; /** * Controller is the base class for cl ...

  7. Yii源码阅读笔记(十九)

    View中渲染view视图文件的前置和后置方法,以及渲染动态内容的方法: /** * @return string|boolean the view file currently being rend ...

  8. Yii源码阅读笔记(一)

    今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...

  9. Yii源码阅读笔记(二)

    接下来阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— namespace yii; use yii\base\InvalidConfigExceptio ...

  10. Werkzeug源码阅读笔记(三)

    这次主要讲下werkzeug中的Local. 源码在werkzeug/local.py Thread Local 在Python中,状态是保存在对象中.Thread Local是一种特殊的对象,它是对 ...

随机推荐

  1. T-SQL 语句的理解

    1.T-SQL中各子句在逻辑上按照以下顺序进行处理 . . . .. .ORDER BY 查询实例: SELECT EMPID, YEAR(ORDERDATE) AS ORDERYEAR, COUNT ...

  2. ACM/ICPC 之 混合图的欧拉回路判定-网络流(POJ1637)

    //网络流判定混合图欧拉回路 //通过网络流使得各点的出入度相同则possible,否则impossible //残留网络的权值为可改变方向的次数,即n个双向边则有n次 //Time:157Ms Me ...

  3. Shell判断字符串包含关系的几种方法

    现在每次分析网站日志的时候都需要判断百度蜘蛛是不是真实的蜘蛛,nslookup之后需要判断结果中是否包含“baidu”字符串 以下给出一些shell中判断字符串包含的方法,来源程序员问答网站 stac ...

  4. [BI项目记]-配置Sharepoint2013支持文档版本管理笔记

    做开发或者做方案,写文档是很重要的一个工作,我们经常需要知道文档被修改的次数,谁在什么时间修改的文档,以及在某一个版本中,都修改了哪些内容,以及不同版本的文档之间有什么差别. 如何对文档进行版本管理, ...

  5. C++ 系列:C++ 基础 001

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  6. 算法系列:Fibonacci

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  7. 在ASP.NET MVC项目中使用React

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:最近在开发钉钉的微应用,考虑到性能和UI库的支持,遂采用了React来开发前端. 目前 ...

  8. UITableView在设置contentOffset的同时也reload,造成tableView的contentOffset偏差

    最近在写一个聊天的框架,遇到一个奇葩的问题,就是发送聊天记录的时候(需要tableView上移,显示出最新的记录),增加一条记录无疑需要reload一下(大家都明白的),这是就会出现头疼的问题,页面显 ...

  9. [spring源码学习]五-BeanPostProcessor的使用

    一.接口描述 spring提供了一个接口类-BeanPostProcessor,我们叫他:bean的加工器,应该是在bean的实例化过程中对bean做一些包装处理,里边提供两个方法 public in ...

  10. BlockingQueue深入分析(转)

    1.BlockingQueue定义的常用方法如下   抛出异常 特殊值 阻塞 超时 插入 add(e) offer(e) put(e) offer(e,time,unit) 移除 remove() p ...