依存関係の循環エラー抑制
ContainerJSでは、コンポーネントの依存関係が循環している場合でも単純な循環であればエラーとせずに依存関係を解決できたりします。たとえば以下のようなパターンであれば問題なく解決可能です。
function main() { // 循環参照するコンポーネントも以下のパターンであれば問題なく依存関係を解決できる。 var c = new container.Container( function( binder ) { // コンポーネント "mii" binder.bind( Kitten ).to( "mii" ).inject({ // "tora" をインジェクト friend : container.component( "tora" ), name : "mii" }); // コンポーネント "tora" binder.bind( Kitten ).to( "tora" ).inject({ // "tora" をインジェクト friend : container.component( "mii" ), name : "tora" }); }); var out = document.getElementById("out"); out.innerHTML += c.get("mii").toString() + "<br/>"; out.innerHTML += c.get("tora").toString() + "<br/>"; } function Kitten() { this.friend = null; this.name = null; } Kitten.prototype = { toString : function() { return "name=" + this.name + " friend=" + this.friend.name; } }
内部的には、「依存モジュールのインジェクションを行う前に、コンポーネントを作成しキャシュとして登録しておくことで循環エラーを回避する」ようになっていて、↑の場合であれば、
- "mii"として登録されたコンストラクタが呼び出され、インスタンスが作成される。
- "mii"はシングルトンなので、インスタンスがキャッシュに登録される。
- "mii"のinject()で指定されたコンポーネントが注入される。
という流れで、最終的に期待されたコンポーネントを保持するインスタンスが作成されます。
ただし、この方式だと以下のような問題はあります。
- コンストラクタインジェクションはできない。
- 依存関係の解決なしにインスタンスを生成できる必要があるため。
- 初期化関数呼び出しのタイミンクでは、インジェクションされたコンポーネントの依存関係が解決されていない場合がある。
function main() { var c = new container.Container( function( binder ) { // コンポーネント "mii" binder.bind( Kitten ).to( "mii" ).inject({ // "tora" をインジェクト friend : container.component( "tora" ), name : "mii" }).initialize("init"); // 初期化メソッドとして"init"を実行 // コンポーネント "tora" binder.bind( Kitten ).to( "tora" ).inject({ // "tora" をインジェクト friend : container.component( "mii" ), name : "tora" }).initialize("init"); // 初期化メソッドとして"init"を実行 }); var out = document.getElementById("out"); c.get("mii"); } // テスト用クラス function Kitten() { this.friend = null; this.name = null; } Kitten.prototype = { init : function() { //初期化メソッドとして呼び出される関数。 //循環参照がある場合、依存コンポーネントのインジェクションは完了していない場合がある。 var out = document.getElementById("out"); out.innerHTML += this.toString() + "<br/>"; }, toString : function() { return "name=" + this.name + " friend=" + this.friend.name; } }
ということでご注意。今日は2つめの問題にはまって、30分ほど悩んだよ・・・。orz。