Yii源码阅读笔记(三十三)
ServiceLocator,服务定位类,用于yii2中的依赖注入,通过以ID为索引的方式缓存服务或则组件的实例来定位服务或者组件:
namespace yii\di; use Yii; use Closure; use yii\base\Component; use yii\base\InvalidConfigException; /** * ServiceLocator implements a [service locator](http://en.wikipedia.org/wiki/Service_locator_pattern). * * To use ServiceLocator, you first need to register component IDs with the corresponding component * definitions with the locator by calling [[set()]] or [[setComponents()]]. * You can then call [[get()]] to retrieve a component with the specified ID. The locator will automatically * instantiate and configure the component according to the definition. * * For example, * * ```php * $locator = new \yii\di\ServiceLocator; * $locator->setComponents([ * 'db' => [ * 'class' => 'yii\db\Connection', * 'dsn' => 'sqlite:path/to/file.db', * ], * 'cache' => [ * 'class' => 'yii\caching\DbCache', * 'db' => 'db', * ], * ]); * * $db = $locator->get('db'); // or $locator->db * $cache = $locator->get('cache'); // or $locator->cache * ``` * * Because [[\yii\base\Module]] extends from ServiceLocator, modules and the application are all service locators. * * @property array $components The list of the component definitions or the loaded component instances (ID => * definition or instance). * * @author Qiang Xue <qiang.xue@gmail.com> * @since 2.0 */ class ServiceLocator extends Component { /** * @var array shared component instances indexed by their IDs * @var array 用于缓存服务、组件等的实例,索引为ID */ private $_components = []; /** * @var array component definitions indexed by their IDs * @var array 用于保存服务和组件的定义,通常为配置数组,可以用来创建具体的实例 */ private $_definitions = []; /** * Getter magic method. * 重写了 getter 方法,使得访问服务和组件就跟访问类的属性一样。同时,也保留了原来Component的 getter所具有的功能。 * This method is overridden to support accessing components like reading properties. * @param string $name component or property name * @return mixed the named property value */ public function __get($name) { if ($this->has($name)) {//调用has方法判断是否有某个组件或服务的实例,如果有调用get方法返回该实例 return $this->get($name); } else {//否则把$name当普通属性处理 return parent::__get($name); } } /** * Checks if a property value is null. * 重写了 isset 方法,增加了对是否具有某个服务和组件的判断 * This method overrides the parent implementation by checking if the named component is loaded. * @param string $name the property name or the event name * @return boolean whether the property value is null */ public function __isset($name) { if ($this->has($name, true)) {//调用has方法判断是否有某个组件或服务的实例,如果有返回true return true; } else {//否则判断是否有$name这个属性 return parent::__isset($name); } } /** * Returns a value indicating whether the locator has the specified component definition or has instantiated the component. * This method may return different results depending on the value of `$checkInstance`. * 当 $checkInstance === false 时,用于判断是否已经定义了某个服务或组件 * 当 $checkInstance === true 时,用于判断是否已经有了某个服务或组件的实例 * * - If `$checkInstance` is false (default), the method will return a value indicating whether the locator has the specified * component definition. * - If `$checkInstance` is true, the method will return a value indicating whether the locator has * instantiated the specified component. * * @param string $id component ID (e.g. `db`). * @param boolean $checkInstance whether the method should check if the component is shared and instantiated. * @return boolean whether the locator has the specified component definition or has instantiated the component. * @see set() */ public function has($id, $checkInstance = false) { return $checkInstance ? isset($this->_components[$id]) : isset($this->_definitions[$id]); } /** * Returns the component instance with the specified ID. * 根据 $id 获取对应的服务或组件的实例 * * @param string $id component ID (e.g. `db`). * @param boolean $throwException whether to throw an exception if `$id` is not registered with the locator before. * @return object|null the component of the specified ID. If `$throwException` is false and `$id` * is not registered before, null will be returned. * @throws InvalidConfigException if `$id` refers to a nonexistent component ID * @see has() * @see set() */ public function get($id, $throwException = true) { if (isset($this->_components[$id])) {//如果_components中有该组件或者服务的实例 return $this->_components[$id];//返回该实例 } if (isset($this->_definitions[$id])) {//如果_definitions中定义了该组件或者服务 $definition = $this->_definitions[$id];//取得该组件或者服务的值 if (is_object($definition) && !$definition instanceof Closure) {//如果该值是对象实例且不是Closure(匿名)的实例 return $this->_components[$id] = $definition;//则在_components注册该组件或者服务的实例并返回 } else { return $this->_components[$id] = Yii::createObject($definition);//否则根据定义中的配置参数创建实例并注册返回 } } elseif ($throwException) {//如果允许抛出异常,则抛出异常 throw new InvalidConfigException("Unknown component ID: $id"); } else {//否则返回null return null; } } /** * Registers a component definition with this locator. * 用于注册一个组件或服务,其中 $id 用于标识服务或组件。 * $definition 可以是一个类名,一个配置数组,一个PHP callable(回调函数),或者一个对象 * * For example, * * ```php * // a class name * $locator->set('cache', 'yii\caching\FileCache'); * * // a configuration array * $locator->set('db', [ * 'class' => 'yii\db\Connection', * 'dsn' => 'mysql:host=127.0.0.1;dbname=demo', * 'username' => 'root', * 'password' => '', * 'charset' => 'utf8', * ]); * * // an anonymous function * $locator->set('cache', function ($params) { * return new \yii\caching\FileCache; * }); * * // an instance * $locator->set('cache', new \yii\caching\FileCache); * ``` * * If a component definition with the same ID already exists, it will be overwritten. * * @param string $id component ID (e.g. `db`). * @param mixed $definition the component definition to be registered with this locator. * It can be one of the following: * * - a class name * - a configuration array: the array contains name-value pairs that will be used to * initialize the property values of the newly created object when [[get()]] is called. * The `class` element is required and stands for the the class of the object to be created. * - a PHP callable: either an anonymous function or an array representing a class method (e.g. `['Foo', 'bar']`). * The callable will be called by [[get()]] to return an object associated with the specified component ID. * - an object: When [[get()]] is called, this object will be returned. * * @throws InvalidConfigException if the definition is an invalid configuration array */ public function set($id, $definition) { if ($definition === null) {//如果$definition为null,即只传入$id,表示删除 unset($this->_components[$id], $this->_definitions[$id]); return; } unset($this->_components[$id]);//开始时清空_components中的id if (is_object($definition) || is_callable($definition, true)) {//如果传入的$definition是一个类名一个PHP callable(回调函数),或者一个对象 // an object, a class name, or a PHP callable $this->_definitions[$id] = $definition;//直接储存到_definitions中 } elseif (is_array($definition)) {//如果传入的$definition是一个数组 // a configuration array if (isset($definition['class'])) {//且数组中存在类名 $this->_definitions[$id] = $definition;//则将该数组储存到_definitions中 } else {//否则,抛出异常 throw new InvalidConfigException("The configuration for the \"$id\" component must contain a \"class\" element."); } } else {//否则,抛出异常 throw new InvalidConfigException("Unexpected configuration type for the \"$id\" component: " . gettype($definition)); } } /** * Removes the component from the locator. * 删除一个服务或组件 * @param string $id the component ID */ public function clear($id) { unset($this->_definitions[$id], $this->_components[$id]); } /** * Returns the list of the component definitions or the loaded component instances. * 用于返回Service Locator的 $_components 数组或 $_definitions 数组, * 同时也是 components 属性的getter函数 * @param boolean $returnDefinitions whether to return component definitions instead of the loaded component instances. * @return array the list of the component definitions or the loaded component instances (ID => definition or instance). */ public function getComponents($returnDefinitions = true) { return $returnDefinitions ? $this->_definitions : $this->_components; } /** * Registers a set of component definitions in this locator. * 批量方式注册组件,同时也是 components 属性的setter函数 * 其实就是以数组的方式传入set方法的参数,遍历后调用set * * This is the bulk version of [[set()]]. The parameter should be an array * whose keys are component IDs and values the corresponding component definitions. * * For more details on how to specify component IDs and definitions, please refer to [[set()]]. * * If a component definition with the same ID already exists, it will be overwritten. * * The following is an example for registering two component definitions: * * ```php * [ * 'db' => [ * 'class' => 'yii\db\Connection', * 'dsn' => 'sqlite:path/to/file.db', * ], * 'cache' => [ * 'class' => 'yii\caching\DbCache', * 'db' => 'db', * ], * ] * ``` * * @param array $components component definitions or instances */ public function setComponents($components) { foreach ($components as $id => $component) { $this->set($id, $component); } } }
Yii源码阅读笔记(三十三)的更多相关文章
- Yii源码阅读笔记(十三)
Model类,集中整个应用的数据和业务逻辑: namespace yii\base; use Yii; use ArrayAccess; use ArrayObject; use ArrayItera ...
- Yii源码阅读笔记(一)
今天开始阅读yii2的源码,想深入了解一下yii框架的工作原理,同时学习一下优秀的编码规范和风格.在此记录一下阅读中的小心得. 每个框架都有一个入口文件,首先从入口文件开始,yii2的入口文件位于we ...
- Werkzeug源码阅读笔记(三)
这次主要讲下werkzeug中的Local. 源码在werkzeug/local.py Thread Local 在Python中,状态是保存在对象中.Thread Local是一种特殊的对象,它是对 ...
- Yii源码阅读笔记(三)
接着上次的继续阅读BaseYii.php vendor/yiisoft/yii2/BaseYii.php—— public static function getRootAlias($alias)// ...
- Yii源码阅读笔记(三十五)
Container,用于动态地创建.注入依赖单元,映射依赖关系等功能,减少了许多代码量,降低代码耦合程度,提高项目的可维护性. namespace yii\di; use ReflectionClas ...
- Yii源码阅读笔记(三十四)
Instance类, 表示依赖注入容器或服务定位器中对某一个对象的引用 namespace yii\di; use Yii; use yii\base\InvalidConfigException; ...
- Yii源码阅读笔记(三十二)
web/Application类的注释,继承base/Application类,针对web应用的一些处理: namespace yii\web; use Yii; use yii\base\Inval ...
- Yii源码阅读笔记(三十一)
Widget类中开始,获取视图对象,获取widget ID,渲染视图,获取路径方法注释: private $_id; /** * Returns the ID of the widget. * 返回插 ...
- Yii源码阅读笔记(三十)
Widget类是所有小部件的基类,开始,结束和渲染小部件内容的方法的注释: namespace yii\base; use Yii; use ReflectionClass; /** * Widget ...
随机推荐
- (备忘)自定义viewgroup与点击分发事件
public class ScoreButton extends ViewGroup 在类中重写onTouchEvent方法 @Override public boolean onTouchEvent ...
- MySql: show databases/tables use database desc table
1. show databases mysql> show databases;+--------------------+| Database |+--------------------+| ...
- CCProxy二级代理上网设置
假如电脑A可以通过代理服务器上网,B电脑又可以连接A电脑,那么A电脑可以作为二级代理服务器进行上网,需要设置如下: 1.在A电脑上安装CCProxy,以v8.0为例 2.选择设置->高级 3.启 ...
- 51nod1228 序列求和(自然数幂和)
与UVA766 Sum of powers类似,见http://www.cnblogs.com/IMGavin/p/5948824.html 由于结果对MOD取模,使用逆元 #include<c ...
- MySQL - 常用命令及常用查询SQL
常用查询SQL #查看临时目录 SHOW VARIABLES LIKE '%tmp%'; #查看当前版本 SELECT VERSION(); 常用命令 #查看当前版本,终端下未进入mysql mysq ...
- JavaScript预解析1
var 不一定是用来定义局部变量的 jscript的全局变量和局部变量的分界是这样的: 过程体(包括方法function,对象Object o ={})外的所有变量不 ...
- 2015ACM/ICPC亚洲区沈阳站
5510 Bazinga 题意:给出n个字符串,求满足条件的最大下标值或层数 条件:该字符串之前存在不是 它的子串 的字符串 求解si是不是sj的子串,可以用kmp算法之类的. strstr是黑科技, ...
- js查找水仙花数
所谓水仙花数是满足类似于153=1³+5³+3³: 第一种方式:把这个数当做字符串来实现 <script> for(var i=100;i<=999;i++) { str_i=i.t ...
- Listener refused the connection with the following error 错误解决
原文地址 :http://blog.csdn.net/zajin/article/details/17753351 做个备份: 查询数据库当前进程的连接数: select count(*) from ...
- Leetcode Substring with Concatenation of All Words
You are given a string, S, and a list of words, L, that are all of the same length. Find all startin ...