nablarch-fw-scoped-container
仕様
JSR330へ準拠している(TCKをパスしている)。
標準で次のスコープをサポートしている。 カッコ内はそれぞれ対応するアノテーション。
- シングルトン(
@Singleton
) - プロトタイプ(
@Prototype
) - リクエストスコープ(
@RequestScoped
) - セッションスコープ(
@SessionScoped
)
インジェクションを行うためのアノテーションは@Inject
。
@RequestScoped
public class HelloAction {
@Inject
private HelloService service;
(省略)
}
インジェクションの方法は次の3つをサポートしている。
- コンストラクターインジェクション
- フィールドインジェクション
- メソッドインジェクション
限定子を使うことで同じ型で解決できるコンポーネントを複数扱うことができる。
public interface Hello {
(省略)
}
@Named("foo")
public class FooHello implements Hello {
(省略)
}
@Named("bar")
public class BarHello implements Hello {
(省略)
}
@Singleton
public class HelloService {
@Inject
@Named("foo")
private Hello foo;
@Inject
@Named("bar")
private Hello bar;
(省略)
}
コンポーネントの型やスーパークラス、実装インターフェースで宣言されたフィールド・パラメーターにインジェクションできる。 これはつまりFoo
インターフェースがあり、それの実装クラスとしてFooImpl
があった場合、FooImpl
型のコンポーネントをFoo
型のフィールド・パラメーターにインジェクションできるということ。
public interface Foo {
}
@Singleton
public class FooImpl implements Foo {
}
@Inject
private Foo foo; //FooImplをインジェクションできる
次のようなインターフェース、クラスがあったとする。
public interface Foo {}
@Singleton
public class FooImpl implements Foo {}
public interface Bar extends Foo {}
@Singleton
public class BarImpl extends FooImpl implements Bar {}
public interface Baz {}
@Named("xyz")
public class BazImpl {}
このときインジェクションがサポートされる型の関係性は次の通り。
インジェクションされるフォールド・パラメーターの型 | コンポーネントの型 |
---|---|
Foo |
FooImpl |
FooImpl |
FooImpl |
Bar |
BarImpl |
BarImpl |
BarImpl |
Foo |
BarImpl |
FooImpl |
BarImpl |
Baz |
BazImpl |
BazImpl |
BazImpl |
@Named("xyz") Baz |
BazImpl |
@Named("xyz") BazImpl |
BazImpl |
初期化、破棄を行うライフサイクルメソッドをサポートしている。 それぞれ@Init
、@Destroy
というアノテーションを引数なしのメソッドに付ける。 ただし、@Destory
はシングルトン(@Singleton
)でのみ有効である。
@Init
public void init() {
(省略)
}
@Destroy
public void destroy() {
(省略)
}
任意のイベントを発火、ハンドリングする機能をサポートする。 イベントの発火はEventTrigger
インターフェースを通じて行われる。
@Inject
private EventTrigger trigger;
public void login() {
(省略)
LoginSuccessEvent event = ...
trigger.fire(event);
}
イベントのハンドリングを行うメソッドは@Observes
を付けて引数にイベントを取る。
@Observes
public void changeSessionId(LoginSuccessEvent event) {
(省略)
}
制限事項
static
フィールド・static
メソッドにはインジェクションできない- より広いスコープのコンポーネントにはインジェクションできない
- 依存関係が循環してはいけない
より広いスコープのコンポーネントにはインジェクションできないとは例えば次のようなものを指す。
@Singleton
public class Foo {
@Inject
private Bar bar;
(省略)
}
@RequestScoped
public class Bar {
(省略)
}
Foo
はシングルトンなのでDIコンテナが破棄されるまで1つのインスタンスが生存する。 Bar
はリクエストスコープなのでリクエストが終了すれば破棄されるが、シングルトンなFoo
が保持しているのでリクエストが終了しても残り続けることになる。
コンポーネントのインスタンス生成を遅延させるための仕組みとしてjavax.inject.Provider
がある。 これを使えば上記の例は解決できる。
@Singleton
public class Foo {
@Inject
private Provider<Bar> barProvider;
(省略)
}
Bar
を使用するときはbarProvider.get()
でインスタンスを取得する。 その際、内部的にはDIコンテナからインスタンスを取得するのでスコープを気にする必要はない。
使用方法
TraversalConfig
の実装クラスを作成する。
package com.nablarch.example.app;
import nablarch.fw.dicontainer.annotation.auto.TraversalConfig;
public class DIConfig implements TraversalConfig {
}
次のパスへテキストファイルを作成する。
src/main/resources/META-INF/services/nablarch.fw.dicontainer.annotation.auto.TraversalConfig
テキストファイルの内容はTraversalConfig
実装クラスの完全修飾名。
com.nablarch.example.app.DIConfig
いくつかのコンポーネントを定義する。
<component name="nablarchWebContextHandler" class="nablarch.fw.dicontainer.nablarch.NablarchWebContextHandler"/>
<component name="annotationAutoContainerProvider" class="nablarch.fw.dicontainer.nablarch.AnnotationAutoContainerProvider">
<property name="requestContextSupplier" ref="nablarchWebContextHandler"/>
<property name="sessionContextSupplier" ref="nablarchWebContextHandler"/>
</component>
ハンドラキュー構成にnablarchWebContextHandler
を追加する。 nablarchWebContextHandler
がリクエストスコープ、セッションスコープを使用するためにExecutionContext
からコンテキストを構築してスレッドローカルに保存する。 JSPフォワード時にDIコンテナを参照する場合は、HttpResponseHandlerより上に配置する。
<component name="webFrontController"
class="nablarch.fw.web.servlet.WebFrontController">
<property name="handlerQueue">
<list>
(中略)
<!-- JSPフォワード時にDIコンテナを参照する場合は、HttpResponseHandlerより上に配置する -->
<component-ref name="nablarchWebContextHandler"/>
<component class="nablarch.fw.web.handler.HttpResponseHandler"/>
(中略)
</list>
</property>
</component>
初期化が必要なコンポーネントとしてAnnotationAutoContainerProvider
を設定する。 この初期化処理でDIコンテナが作られる。
<component name="initializer"
class="nablarch.core.repository.initialization.BasicApplicationInitializer">
<property name="initializeList">
<list>
(省略)
<component-ref name="annotationAutoContainerProvider"/>
</list>
</property>
</component>
RoutesMapping
の定義へContainerLookupDelegateFactory
を設定する。 ContainerLookupDelegateFactory
がDIコンテナからアクションを取り出す役割を担っている。
<component name="packageMapping"
class="nablarch.integration.router.RoutesMapping">
(中略)
<property name="delegateFactory">
<component class="nablarch.fw.dicontainer.nablarch.ContainerLookupDelegateFactory"/>
</property>
</component>
BeanValidationStrategy
の定義へContainerLookupBeanValidationFormFactory
を設定する。 ContainerLookupBeanValidationFormFactory
がDIコンテナからフォームを取り出す役割を担っている。
<component name="validationStrategy" class="nablarch.common.web.validator.BeanValidationStrategy">
<property name="formFactory">
<component class="nablarch.fw.dicontainer.nablarch.ContainerLookupBeanValidationFormFactory" />
</property>
</component>
参考:https://github.com/nablarch/nablarch-example-web/commit/3832b312f4905a9ee437d9266bd306cb687d4340
内部構造
パッケージ構成
パッケージ | 説明 |
---|---|
nablarch.fw.dicontainer |
DIコンテナのインターフェースといくつかのアノテーションが含まれる |
nablarch.fw.dicontainer.component |
コンポーネント定義や検索キーが含まれる |
nablarch.fw.dicontainer.component.factory |
コンポーネント定義や検索キーのファクトリーのインターフェースが含まれる |
nablarch.fw.dicontainer.component.impl |
コンポーネントの構成要素の実装クラスが含まれる |
nablarch.fw.dicontainer.component.impl.reflect |
リフレクションをラップするクラスが含まれる |
nablarch.fw.dicontainer.annotation |
アノテーションをもとにDIコンテナを構築するためのクラスが含まれる |
nablarch.fw.dicontainer.annotation.auto |
ディレクトリトラバーサルを行なって自動でDIコンテナを構築するためのクラスが含まれる |
nablarch.fw.dicontainer.scope |
スコープに関連するクラスが含まれる |
nablarch.fw.dicontainer.container |
DIコンテナの実装クラスが含まれる |
nablarch.fw.dicontainer.exception |
例外クラスが含まれる |
nablarch.fw.dicontainer.event |
DIコンテナが発火させるイベントが含まれる |
nablarch.fw.dicontainer.web |
リクエストスコープ、セッションスコープのアノテーションが含まれる |
nablarch.fw.dicontainer.web.exception |
Webに関する例外クラスが含まれる |
nablarch.fw.dicontainer.web.context |
リクエストスコープ、セッションスコープを実現するためのクラスが含まれる |
nablarch.fw.dicontainer.web.scope |
リクエストスコープ、セッションスコープの実装クラスが含まれる |
nablarch.fw.dicontainer.nablarch |
NablarchでDIコンテナを使用するためのクラスが含まれる |