S2Containerの生成はS2ApplicationContextクラスのcreateメソッドで行います。
require 's2container' container = Seasar::Container::S2ApplicationContext.instance.create
S2ApplicationContext instanceを返すs2appメソッドを使用して、次のようにS2Containerを生成できます。
require 's2container' container = s2app.create
S2Containerからコンポーネントを取り出すには、次のメソッドを使用します。
S2Container#get_component(component_key)
引数にはコンポーネントのクラス、または文字列及びSymbolでコンポーネント名を指定します。
S2Containerに登録されているコンポーネント中に、指定したクラスを実装しているコンポーネントが複数ある場合は、S2Containerはどの
コンポーネントを返せばよいのか判断できないためTooManyRegistrationRuntimeExceptionをraiseします。
実装コンポーネントがユニークに決まるクラスを指定してください。
コンポーネント名で取得する場合も同様に、1つのS2Containerの中でユニークとなるコンポーネント名を指定します。
同じ名前をもつコンポーネントが複数登録されている場合は、TooManyRegistrationRuntimeExceptionが発生します。
例として次のようなクラスを定義します。 s2componentメソッドの引数でコンポーネント名を文字列及びSymbolで設定します。
module Example class IndexAction s2component :name => "index" end class TopAction s2component :name => :top end class ResultAction s2component end end
コンポーネント名を文字列で指定してコンポーネントを取得する場合は次のようになります。
require 's2container' require 'example' container = s2app.create component = container.get_component("index")
クラスを指定してコンポーネントを取得する場合は次のようになります。componentメソッドはget_componenntメソッドのaliasです。
component = container.component(Example::IndexAction)
コンポーネント名をSymbolで指定してコンポーネントを取得する場合は次のようになります。getメソッドはget_componentメソッドのaliasです。
component = container.get(:top)
S2Contaienrからコンポーネントを取得するメソッドとして[]も使用できます。
component = container[Example::ResultAction]
NOTE | |
---|---|
この例は example/example01 にあります。 |
S2ContainerのDependency Injectionは、自動バインディングによるプロパティ・インジェクションです。 インスタンス変数とアクセッサメソッドがプロパティとして扱われます。 自動バインディングは、コンポーネント間の依存関係を、プロパティ名やデフォルト値で指定されるクラスやコンポーネント名で解決します。
次のようなクラスを定義します。Actionクラスのコンストラクタinitializeメソッドで、インスタンス変数を定義します。インスタンス変数の デフォルト値に、Actionコンポーネントが依存する各ServiceコンポーネントをDIするための情報を設定しています。 また、attr_accessorメソッドでプロパティ「d」を定義しているため、コンポーネント名が「d」のコンポーネントがDIされます。
module Example class Action s2comp def initialize @a = nil @b = :di, "x.y.z.service_b" @c = :di, ServiceC @x_ = nil @_x = nil end attr_reader :a, :b, :c attr_accessor :d end class ServiceA s2comp :name => :a end class ServiceB s2comp :name => "service_b", :namespace => "x.y.z" end class ServiceC s2comp end class ServiceD s2comp :name => :d end end
次のような実行ファイルを作成します。S2ContainerからActionコンポーネントを取得すると、インスタンス変数aからfに 各ServiceインスタンスがDIされたActionコンポーネントのインスタンスが返されます。
require 's2container' require 'example' container = s2app.create component = container[Example::Action]
インスタンス変数名の先頭・後方にアンダースコアが付いたインスタンス変数は、自動バインディングの対象外となります。 コンポーネント間の依存関係を、プロパティのデフォルト値で設定するフォーマット一覧を次に示します。
表3.1 プロパティ値とDI
プロパティ値 説明 例 nil インスタンス変数名のSymbol値をコンポーネント名としてDIします。インスタンス変数名が「@a」の場合、コンポーネント名は「:a」となります。 @property = nil Array Arrayの sizeが2で、一番目の値が文字列かSymbolで「di」の場合に、二番目の値をコンポーネント名としてDIします。 @property = :di, "service"
NOTE | |
---|---|
この例は example/example02 にあります。 |
コンストラクタ ブロックとは、コンポーネントの生成処理を行うブロックです。コンストラクタ ブロックは、s2componentメソッドで クラスをコンポーネントととして登録する際に設定します。
次のようなクラスを定義します。
module Example class Action def initialize(val) @val = val end attr_accessof :val end end
次のような実行ファイルを作成します。s2componentメソッドにコンストラクタ ブロックを渡します。 コンストラクタ ブロックの最後の評価結果は、コンポーネントクラスとis_a?関係でなければいけません。
require 's2container' require 'example' s2component(:class => Example::Action) { Example::Action.new("abc") } container = s2app.create component = container[Example::Action] p component.val # -> "abc"
NOTE | |
---|---|
この例は example/example03 にあります。 |
デストラクタ ブロックとは、コンポーネントのDestroy処理を行うブロックです。コンポーネントのインスタンス設定がsingletonの場合にのみ実行されます。 デストラクタ ブロックは、s2containerのdestroyメソッド内で実行されます。
次のようなクラスを定義します。
module Example class Action def init s2logger.debug(self.class){"init method called as constructor."} end def quit s2logger.debug(self.class){"quit method called as destructor."} end end end
次のような実行ファイルを作成します。s2componentメソッドでコンポーネントを登録します。戻り値のComponentInfoDefに デストラクタ ブロックを設定します。
require 's2container' require 'example' component_info = s2component(:class => Example::Action) { # constructor block action = Example::Action.new action.init next action } component_info.destructor {|component| # destructor block component.quit } container = s2app.create container.init # call constructor block container.destroy # call destructor block
S2Containerでは、コンポーネント単位でバインディングタイプを指定できます。バインディングタイプは次の2つがあります。
表3.2 バインディングタイプ
autoBinding 説明 :auto (default) プロパティのデフォルト値により自動的にバインドします。 :none コンストラクタの引数が明示的に指定されている場合は、それに従います。
プロパティが明示的に指定されている場合は、それに従います。
s2componentメソッドでバインディングタイプを指定する場合は次のようになります。
class Service s2component :autobinding => :auto end
S2Containerでは、コンポーネント単位でインスタンスの管理方法を指定できます。インスタンスタイプは次の2つがあります。
表3.3 インスタンスタイプ
instance 説明 :singleton (default) S2Container.get_componentでコンポーネントを取得すると、常に同じインスタンスが返されます。 :prototype S2Container.get_componentでコンポーネントを取得すると、常に新規インスタンスが返されます。
s2componentメソッドでインスタンスタイプを指定する場合は次のようになります。
class Service s2component :instance => :singleton end
© Copyright The Seasar Foundation and the others 2008-2009, all rights reserved. |