首頁 > 後端開發 > php教程 > yii2 隨筆(七)依賴注入-(4)服務定位器

yii2 隨筆(七)依賴注入-(4)服務定位器

黄舟
發布: 2023-03-04 21:20:01
原創
1417 人瀏覽過

服務定位器定位器是依賴注入的一種解決方式,它包含依賴注入,在解決了依賴注入後,如果服務使用者和服務提供者不是用一個人,那麼使用者要了解提供服務的必須參數,這樣才能確保依賴的正確性,這就耦合了使用者和提供者,服務定位器就是解耦這部分的,服務提供者在ServiceLocator 中註冊服務(同時註冊了依賴),僅僅告訴服務使用者那些服務的名稱或別名,那麼對於服務提供者和使用者都是好的,使用者只需要知道提供者提供的什麼服務,而不必知道依賴什麼,服務提供者也不必為使用者「胡亂使用」服務而導致的bug所困擾。

那麼yii2是怎麼使用ServiceLocator呢?其實很簡單如下

//魔术方法,
public function __get($name){
    //得到某个注册的方法
    if ($this->has($name)) {
        return $this->get($name);
    } else {
        return parent::__get($name);
    }
}
//魔术方法查看某个服务是否存在,源码略
public function __isset($name){}
//__isset()中调用,查看某个服务是否存在,源码略
public function has($id, $checkInstance = false){}
//得到某个服务
public function get($id, $throwException = true)
{
    if (isset($this->_components[$id])) {//如果是已经处理的服务,就直接返回
        return $this->_components[$id];
    }

    if (isset($this->_definitions[$id])) {//如定义了该服务
        $definition = $this->_definitions[$id];//得到服务的定义
        //如果服务是一个闭包,则把闭包注册到已经实例化的服务中,并且返回闭包
        if (is_object($definition) && !$definition instanceof Closure) {
            return $this->_components[$id] = $definition;
        } else {//其他的情况下通过依赖注入生成对象,并且注册为已处理,返回对象
            return $this->_components[$id] = Yii::createObject($definition);
        }
    } elseif ($throwException) {//如果抛出异常,则抛出异常
        throw new InvalidConfigException("Unknown component ID: $id");
    } else {//其他返回null
        return null;
    }
}
//注册一个服务
public function set($id, $definition)
{
    if ($definition === null) {//如果该服务的定义为null,则删除已经实例化的服务,返回空,用于注销已经实例化的并且保存过的服务的定义
        unset($this->_components[$id], $this->_definitions[$id]);
        return;
    }
    //清空已经实例化的服务
    unset($this->_components[$id]);
    //如果该服务的定义为一个对象,并且是一个可调用的结构
    if (is_object($definition) || is_callable($definition, true)) {
        // an object, a class name, or a PHP callable
        $this->_definitions[$id] = $definition;
    } elseif (is_array($definition)) {//如果该服务是一个配置数组
        // a configuration array
        if (isset($definition['class'])) {//如果有class键值,则直接注册为一个服务的定义
            $this->_definitions[$id] = $definition;
        } else {//是配置数组,但是没有指定class,则抛出异常
            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));
    }
}
//清空已经实例化过的服务和定义,代码略
public function clear($id){}
//得到已经实例化后的服务,或者得到可用的服务配置
public function getComponents($returnDefinitions = true){}
//注册所有的服务,这里的$components,就是你在config里写的 $config['components']值
public function setComponents($components){}
登入後複製

那麼ServiceLocator是從什麼時候介入的呢?我們繼續開我們的index.php,注意下面那句話

(new yii\web\Application($config))->run();
登入後複製

我們查看Application

class Application extends \yii\base\Application
//继续追踪  \yii\base\Application
abstract class Application extends Module
//继续追踪  Module
class Module extends ServiceLocator
登入後複製
哈,終於找到丫了! ! !我們的application 其實就一個服務定位器,我們在設定檔裡設定的components,都是application的這個服務定位器註冊的服務。這下知道為什麼叫做 setComponents這個函數了吧,不明白繼續往下看。

yii 用 set[typename] 的函式來確保屬性的可寫性,在基底類別 yiibaseObject 的建構子裡使用了 Yii::configure($this, $config);這個會呼叫 setComponents 函式註冊服務。

好啦,前後都聯繫上了,yii2使用的依賴注入和服務定位器,就說到這裡。

以上就是yii2 隨筆(七)依賴注入-(4)服務定位器的內容,更多相關內容請關注PHP中文網(m.sbmmt.com)!


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板