yii2框架随笔25

今天来看Container.php,yii2的容器代码。

<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */
namespace yiidi;
use ReflectionClass;
use yiibaseComponent;
use yiibaseInvalidConfigException;
/**
 * Container implements a [dependency injection](http://en.wikipedia.org/wiki/Dependency_injection) container.
 * 实现了依赖注入容器(http://en.wikipedia.org/wiki/dependency_injection)。
 * A dependency injection (DI) container is an object that knows how to instantiate and configure objects and
 * all their dependent objects.
 * 依赖注入(DI)的容器是一个对象,知道如何实例化和配置所有的依赖对象。
 *  For more information about DI, please refer to
 *  有关更多信息,请参阅
 * [Martin Fowler's article](http://martinfowler.com/articles/injection.html).
 *
 * Container supports constructor injection as well as property injection.
 * 容器支持构造函数注入以及属性注入。
 * To use Container, you first need to set up the class dependencies by calling [[set()]].
 * 使用的容器,你首先需要设置类的依赖关系,通过调用[[set()]]方法。
 * You then call [[get()]] to create a new class object.
 * 然后你可以调用[[get()]]方法创建一个新的类的对象。
 * Container will automatically instantiate
 * dependent objects, inject them into the object being created, configure and finally return the newly created object.
 * 容器会自动实例化依赖对象,将它们注入到正在创建的对象中,配置并最终返回新创建的对象。

 * @property array $definitions The list of the object definitions or the loaded shared objects (type or ID =>
 * definition or instance). This property is read-only.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Container extends Component
{
    /**
     * @var array singleton objects indexed by their types
     * 用于保存单例Singleton对象,以对象类型为键
     */
    private $_singletons = [];
    /**
     * @var array object definitions indexed by their types
     * 用于保存依赖的定义,以对象类型为键
     */
    private $_definitions = [];
    /**
     * @var array constructor parameters indexed by object types
     * 用于保存构造函数的参数,以对象类型为键
     */
    private $_params = [];
    /**
     * @var array cached ReflectionClass objects indexed by class/interface names
     * 用于缓存ReflectionClass对象,以类名或接口名为键
     */
    private $_reflections = [];
    /**
     * @var array cached dependencies indexed by class/interface names. Each class name
     * is associated with a list of constructor parameter types or default values.
     * 用于缓存依赖信息,以类名或接口名为键
     */
    private $_dependencies = [];
    /**
     * Returns an instance of the requested class.
     * 返回所请求的类的实例。
     * You may provide constructor parameters (`$params`) and object configurations (`$config`)
     * that will be used during the creation of the instance.
     * 你可以提供构造函数参数(` $params `)和对象的配置(`$config`),在创建实例时使用。

     * Note that if the class is declared to be singleton by calling [[setSingleton()]],
     * 注意,如果类声明为单称[[setsingleton()]],
     * the same instance of the class will be returned each time this method is called.
     * 每次调用该方法时,该类的同一实例将被返回。
     * In this case, the constructor parameters and object configurations will be used
     * only if the class is instantiated the first time.
     * 在这种情况下,只有当类被实例化的第一时间,将使用构造函数参数和对象配置.
     * @param string $class the class name or an alias name (e.g. `foo`) that was previously registered via [[set()]]
     * or [[setSingleton()]].
     * @param array $params a list of constructor parameter values. The parameters should be provided in the order
     * they appear in the constructor declaration. If you want to skip some parameters, you should index the remaining
     * ones with the integers that represent their positions in the constructor parameter list.
     * @param array $config a list of name-value pairs that will be used to initialize the object properties.
     * @return object an instance of the requested class.
     * @throws InvalidConfigException if the class cannot be recognized or correspond to an invalid definition
     */
    public function get($class, $params = [], $config = [])
    {
        if (isset($this->_singletons[$class])) {
            // singleton
            // 如果Singleton对象的数组中有,就直接返回
            return $this->_singletons[$class];
        } elseif (!isset($this->_definitions[$class])) {
            // 如果定义的数组中没有,就去构建它
            return $this->build($class, $params, $config);
        }
        $definition = $this->_definitions[$class];
        if (is_callable($definition, true)) {
            // 如果$definition是callable,就先将参数合并,再将其中的Instance实例替换掉
            $params = $this->resolveDependencies($this->mergeParams($class, $params));
            // 调用$definition
            $object = call_user_func($definition, $this, $params, $config);
        } elseif (is_array($definition)) {
            // 如果是一个数组
            $concrete = $definition['class'];
            unset($definition['class']);
            // 合并配置和参数
            $config = array_merge($definition, $config);
            $params = $this->mergeParams($class, $params);
            if ($concrete === $class) {
                $object = $this->build($class, $params, $config);
            } else {
                $object = $this->get($concrete, $params, $config);
            }
        } elseif (is_object($definition)) {
            // 如果$definition是个对象,就直接保存到_singletons中
            return $this->_singletons[$class] = $definition;
        } else {
            throw new InvalidConfigException("Unexpected object definition type: " . gettype($definition));
        }
        if (array_key_exists($class, $this->_singletons)) {
            // singleton
            // 如果_singletons中没有这个类的实例,就保存一份
            $this->_singletons[$class] = $object;
        }
        return $object;
    }
原文地址:https://www.cnblogs.com/taokai/p/5470322.html