AngularJS の人気に伴い、JavaScript 分野では依存関係注入が大きな注目を集め始めています。 DI の最も顕著な利点は、再利用可能でテスト可能なコード ユニットの開発です。 この記事では、簡単なコードを使用して DI の実装メカニズムを説明します。DI の長所と短所について詳しくは、「依存性注入をいつ使用する必要がありますか?」を参照してください。
各モジュールは独自の依存関係を宣言し、独自のサービスを提供します。例:
di.service('foo', ['bar'], function foo(bar){ function Foo(){ this.bar = bar; } this.prototype.greeting = function(){ console.log('hello, world'); } return Foo; }); var foo = di.container.get('foo'); foo.greeting();
依存関係注入と CommonJS (または AMD) の違いに注意してください。foo は依存関係バーを積極的に取得せずに宣言するだけで済みます。 これにより、関数 foo は依存関係の場所と構築方法を完全に認識しなくなり、関数 foo がテスト可能で再利用可能なコード単位になります。
サービスの登録とサービスの使用は、別のタイミングで行う必要があります。 特別な依存関係解決ツールとして、DI フレームワークはソフトウェア ユニットのライフ サイクルを登録フェーズと実行フェーズに分割します。 上記の例では、foo サービスと bar サービスが登録フェーズで提供され、これらのサービスは実行フェーズで取得および使用されます。 ほとんどの DI フレームワークは遅延構築戦略を採用しており、これにより登録フェーズでの構築の困難さも回避されます。
サービスのカスタマイズは、登録フェーズの後、運用フェーズの前に行うことができます。 AngularJS 1 では、これらのサービスをカスタマイズするための構成フェーズが導入されており、そのプロバイダーは特殊なファクトリ オブジェクトとして理解できます。 BottleJS は、デコレーターとミドルウェアを使用してサービスのカスタマイズをサポートします。
IoC コンテナを使用して、サービス インスタンスのインデックスを作成したり、サービス プロバイダーを保存したりします。 誰かがサービスを提供すると、そのサービスがコンテナに追加され、誰かがサービスを使用すると、コンテナからプロバイダが検索され、サービス インスタンスが生成されます。 多くの場合、サービス インスタンスはキャッシュできます。
まず、サービスのコンストラクターを登録するために使用される、最も一般的なインターフェイス関数 .service() を実装します。 渡された関数は新たに操作されます。
var di = { container: {} }; di.service = function(name, Constructor) { defineLazyProperty(name, () => new Constructor()); }; function defineLazyProperty(name, getter){ Object.defineProperty(di.container, name, { configurable: true, get: function() { var obj = getter(container); Object.defineProperty(di.container, name, { configurable: false value: obj }); return obj; } }); }
Object.defineProperty はここでサービスのキャッシュに使用されます。 コンストラクターはサービスが初めて構築されるときにのみ呼び出され、その後のアクセスでは IoC コンテナーのプロパティが直接読み取られます。 ES5の標準方式であり、互換性が非常に良いです。 defineLazyProperty() メソッドを使用すると、これらの一般的に使用される登録インターフェイスの実装が非常に直感的になります:
di.factory = function(name, factory) { return defineLazyProperty(name, factory); }; di.provider = function(name, Provider) { return defineLazyProperty(name, function(){ var provider = new Provider(); return provider.$get(); }); }; di.value = function(name, val) { return defineLazyProperty(name, () => val); };
サービスのカスタマイズされたインターフェイスについては詳しく説明しません。統合されたサービスのカスタマイズには統合されたサービス構築メソッドが必要であることに言及する価値があります。直接ではなく、 .defineLazyProperty() を呼び出してプロパティを生成します。 AngularJS のこれらの戦略はプロバイダーによって実装され、他のすべてのサービス登録メソッドはプロバイダーによって実装されます。
上記は JavaScript 依存関係注入の実装の内容です。さらに関連する内容については、PHP 中国語 Web サイト (m.sbmmt.com) に注目してください。