3.2. S2ApplicationContext リファレンス

S2ApplicationContextの主な機能は次になります。


3.2.1. S2ApplicationContextの生成

S2ApplicationContextの生成は、instanceメソッドで行います。

S2ApplicationContext#instance

instanceメソッドでS2ApplicationContextを生成した場合は、Singletonインスタンスが返ります。 新規インスタンスを生成する場合は、newメソッドを使用して下さい。

S2ApplicationContext#new

S2ApplicationContext#instanceメソッドへのショートカットとしてs2appメソッドが定義されています。


3.2.2. コンポーネントの登録

s2componentメソッドを用いてクラスをコンポーネントとして登録します。

s2component(options = {}, &procedure)
alias s2comp s2component
  • 第1引数 : コンポーネントの情報 (Hash)
    • Symbol :class => コンポーネントのクラス
      s2componentメソッドがクラス定義内で呼ばれた場合は、そのクラスがデフォルト値として設定されます。
    • Symbol :name => コンポーネント名 (String | Symbol)
    • Symbol :instance => インスタンス管理設定
    • Symbol :autobinding => 自動バインディング設定
    • Symbol :namespace => S2Container内での名前空間設定 (String)
  • 第2引数 : コンストラクタ ブロック
    コンポーネントの生成処理を含むブロックです。ブロックの最後の評価値は、第1引数の:classで指定したクラスとis_a?関係とならなければいけません。

s2componentメソッドは、コンポーネントクラスに「instance」クラスメソッドを定義します。 「instance」 クラスメソッドは、S2Containerからコンポーネントを取得し返します。

require 's2container'

class Action
  s2component
end

action = Action.instance     # instanceクラスメソッド内でs2app.get(Action)が実行される

3.2.3. S2Containerの生成

S2Containerインスタンスの生成は次のメソッドで行います。

S2ApplicationContext#create(namespaces = [])

生成されるS2Containerは、s2componentメソッドで登録した全クラスをコンポーネントとして持ちます。 namespaces引数(文字列、文字列の配列)を設定した場合は、指定されたnamespaceを含むS2Containerインスタンスが返されます。 例として、グローバル(namespace指定無し)にActionクラスがあり、services namespaceにServiceクラスが ある場合は、次のようにS2Containerを生成できます。

クラスの定義は次になります。

module Example
  class Action
    s2comp
  end

  class Service
    s2comp :namespace => "services"
  end
end

実行スクリプトは次になります。

require 's2container'
require 'example'

// グローバルコンテナの生成
container = s2app.create
component = container.get(Example::Action)
p component
component = container.get(Example::Service)
p component


// services namespace コンテナの生成
container = s2app.create("services")
begin
  component = container.get(Example::Action)  # -> コンポーネントが存在しないのでエラーとなります。
rescue => err
  puts err.message
end
component = container.get(Example::Service)
p component
[注意]NOTE

この例は example/example05 にあります。


3.2.4. コンポーネントの選択

createメソッドでS2Containerを生成する際に、s2componentメソッドで登録されたクラスから一部を選択することができます。

  • default (パターン設定無し) : 登録された全てのクラスをコンポーネントとしてincludeします。
  • Include Pattern : 登録されたクラスに対してパターンにマッチするもののみを使用します。
  • Exclude Pattern : 登録されたクラスに対してパターンにマッチするものは除外します。
  • Include & Exclude : Include PatternとExclude Patternが両方設定されている場合は、Include PatternにマッチしたものからExclude Patternにマッチしたものが除外されます。

include メソッド. 

S2ApplicationContext.include(pattern)
  • 第1引数 : include パターン
    • 正規表現 : コンポーネント名、コンポーネントのクラス名にmatchした場合にincludeします。
    • クラス : コンポーネントクラスと等しい場合にincludeします。
    • 文字列 : コンポーネント名、コンポーネントのクラス名に等しい場合にincludeします。
    • Symbol : コンポーネント名、コンポーネントのクラス名のSymbolに等しい場合にincludeします。


excludeメソッド. 

S2ApplicationContext.exclude(pattern)
  • 第1引数 : exclude パターン
    • 正規表現 : コンポーネント名、コンポーネントのクラス名にmatchした場合にexcludeします。
    • クラス : コンポーネントクラスと等しい場合にexcludeします。
    • 文字列 : コンポーネント名、コンポーネントのクラス名に等しい場合にexcludeします。
    • Symbol : コンポーネント名、コンポーネントのクラス名のSymbolに等しい場合にexcludeします。


3.2.5. 自動アスペクト

コンポーネントの選択でインクルードされたコンポーネントに対して、自動的にアスペクトを適用します。 自動アスペクトの設定は、s2aspectメソッドで行います。

s2aspect(options, &procedure)
  • 第1引数 : アスペクト情報をHashで設定します。
    • Symbol :pattern => デフォルト値は Regexp /.+/ です。
      • 正規表現 : コンポーネント名、コンポーネントのクラス名にmatchした場合にaspect対象となります。
      • クラス : コンポーネントクラスと等しい場合にaspect対象となります。
      • 文字列 : コンポーネント名、コンポーネントのクラス名に等しい場合にaspect対象となります。
      • Symbol : コンポーネント名、コンポーネントのクラス名のSymbolに等しい場合にaspect対象となります。
    • Symbol :pointcut => デフォルト値は Regexp /.+/ です。
      • 正規表現 : メソッド名にmatchした場合にaspect対象となります。
      • 文字列 : メソッド名に等しい場合にaspect対象となります。
      • Symbol : メソッド名に等しい場合にaspect対象となります。
    • Symbol :interceptor => Interceptorコンポーネント名、またはInterceptorインスタンス
  • 第2引数 : Interceptor ブロック
    Interceptor処理を含むブロックです。引数はMethodInvocationインスタンスです。MethodInvocationのproceedメソッドで 次のInterceptor処理、あるいはアスペクト対象のメソッドを実行します。

s2aspectメソッドがクラス定義内で実行された場合は、第1引数の:pattern値に文字列でクラス名が自動設定されます。

ActionクラスのindexメソッドにTraceInterceptorをアスペクトする場合を次に示します。 TraceInterceptorは、予め 「interceptor.trace」としてコンポーネントが登録されています。

module Example
  class Action
    s2comp
    s2aspect :interceptor => "interceptor.trace", :pointcut => :index
    def index
      s2logger.debug(self.class.superclass) {"index action called."}
    end
  end
end

実行スクリプトは次になります。

require 's2container'
require 'example'

container = s2app.create
component = container.get(Example::Action)
component.index
[注意]NOTE

この例は example/example06 にあります。

ActionクラスのindexメソッドにブロックでInterceptorをアスペクトする場合を次に示します。

module Example
  class Action
    s2comp :name => :action
    def index
      s2logger.debug(self.class.superclass) {"index action called."}
    end
  end
end

実行スクリプトは次になります。

require 's2container'
require 'example'

s2aspect(:pattern => :action, :pointcut => :index) {|invocation|
  s2logger.debug(invocation.component_class) {"before"}
  result = invocation.proceed
  s2logger.debug(invocation.component_class) {"after "}
  next result
}

container = s2app.create
component = container.get(:action)
component.index
[注意]NOTE

この例は example/example07 にあります。


3.2.6. Singleton S2Container インスタンスの管理

S2ApplicationContextは、namespace単位でSingleton S2Containerを生成、管理します。 Singleton S2Containerへのアクセスは次のメソッドで行います。

get_componentメソッド. 

S2ApplicationContext#get_component(key, namespaces = [])
alias component get_component
alias get get_component
  • 第1引数 : コンポーネントキー
  • 第2引数 : S2Containerを管理するnamespaces

第1引数で指定されたコンポーネントを取得します。 第2引数で指定されたnamespaceを含むSingleton S2Containerが未作成の場合は、S2ApplicationContext.createメソッド を用いてコンテナを生成します。


get_component_defメソッド. 

S2ApplicationContext#get_component_def(key, namespaces = [])
  • 第1引数 : コンポーネントキー
  • 第2引数 : S2Containerを管理するnamespaces

第1引数で指定されたコンポーネント定義を取得します。 第2引数で指定されたnamespaceを含むSingleton S2Containerが未作成の場合は、S2ApplicationContext.createメソッド を用いてコンテナを生成します。

例として、グローバル(namespace指定無し)にActionクラスがあり、services namespaceにServiceクラスが ある場合は、次のように 各コンポーネントを取得できます。

クラス定義は次になります。

module Example
  class Action
    s2comp
  end

  class Service
    s2comp :namespace => "services"
  end
end

実行スクリプトは次になります。

require 's2container'
require 'example'

global_action = s2app.get(Example::Action)
p global_action
global_service = s2app.get(Example::Service)
p global_service

begin
  services_action = s2app.get(Example::Action, "services")
rescue => err
  puts err.message                # -> component [Example::Action] not found.
end
services_service = s2app.get(Example::Service, "services")
p services_service
p global_service == services_service       # -> false
[注意]注意

グローバルのSingletonコンテナが生成される際にservices namespaceのコンテナも生成され、子コンテナとして保持されていますが、 services namespaceのSingletonコンテナとは別インスタンスとなります。


[注意]NOTE

この例は example/example08 にあります。



© Copyright The Seasar Foundation and the others 2008-2009, all rights reserved.