ホームページ  >  記事  >  バックエンド開発  >  yii2 エッセイ (7) 依存関係の注入 - (4) サービス ロケーター

yii2 エッセイ (7) 依存関係の注入 - (4) サービス ロケーター

黄舟
黄舟オリジナル
2017-01-17 10:38:221394ブラウズ

サービス ロケーター ロケーターは、依存関係の挿入を解決するソリューションです。依存関係の挿入が解決された後、サービス ユーザーとサービス プロバイダーが異なる場合、ユーザーはサービスを提供するために必要なパラメーターを理解する必要があります。依存関係の正確性を保証するために、サービス ロケーターは分離部分であり、サービスを ServiceLocator に登録し (同時に依存関係も登録します)、サービス ユーザーにのみ通知します。 what サービスの名前またはエイリアスは、サービス プロバイダーとユーザーの両方にとって適切です。ユーザーはプロバイダーが提供するサービスを知るだけでよく、何に依存しているかを知る必要はありません。また、サービス プロバイダーはサービスを「使用する」必要はありません。ユーザーにとってはランダムであり、バグによって引き起こされます。

では、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
はー、ついに見つけました! ! !私たちのアプリケーションは、実際には単なるサービス ロケーターです。構成ファイルで構成するコンポーネントはすべて、アプリケーションのサービス ロケーターによって登録されたサービスです。これで、関数が setComponents と呼ばれる理由がわかりました。理解できない場合は、読み続けてください。

yii は set[typename] 関数を使用して属性の書き込み可能性を確保します。 Yii::configure($this, $config) は基本クラス yiibaseObject のコンストラクターで使用され、これによりサービスを登録するために setComponents 関数が呼び出されます。

はい、yii2 が使用する依存関係の注入とサービス ロケーターについては、これで終わりです。

上記は Yii2 Essay (7) dependency Injection - (4) Service Locator の内容です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。