インジェクション はTapestryのキーコンセプトのひとつです。Tapestry IoC コンテナ はサービスビルダメソッドへのパラメータにインジェクションを利用しています。
コンポーネントへのインジェクションには全く別の方針を取っています: インスタンス変数へ直接インジェクションします。
Inject アノテーションを使用し、サービスやその他のリソースをインジェクトするフィールドを指定します。
Tapestryには2種類のインジェクションがあります:
どちらの場合もフィールドはリードオンリーに変換されます。 この変換は実行時に行われます(これは、コンポーネントがテスト可能であるという点において非常に重要なことです)。 インジェクトされたフィールドを変更しようとすると実行時例外が発生します。
またいくつかの特別なケースとして、フィールドがある特定の型である場合や、 Injectアノテーションの他に追加のアノテーションがフィールドに与えられている場合があります。
Pathアノテーションも与えられている場合、 インジェクトされる値は(コンポーネントからの相対パス上にある)ローカライズされたアセットです。
アノテーションの値の中にあるシンボルは展開されます。
Block型のフィールドは、コンポーネントテンプレート内の<block> 要素がインジェクトされます。 通常はフィールド名と同じidを持つblock要素がインジェクトされます(フィールド名の先頭に "_" か "$" がある場合は取り除かれます)。 これが適切でない場合、Idアノテーションを使う事ができます:
@Inject private Block foo; @Inject @Id("bar") private Block barBlock;
ひとつ目のインジェクションでは、idが "foo" のblock要素がインジェクトされます(いつものように、idの大文字小文字は区別されません)。 ふたつ目のインジェクションでは、idが "bar" のblock要素がインジェクトされます。
ある数種類の型のフィールドには、コンポーネントに関連する リソース がインジェクトされます。例えば、コンポーネントのロケールがそうです。
コンポーネントがそれ自身のリソースにアクセスする必要が生じるとき、 というのはリソースインジェクションのとても一般的な例です。 コンポーネントに適切な型のフィールドを定義し、そのフィールドにInjectアノテーション与えます:
@Inject private ComponentResources resources;
Tapestryは、このフィールドに何をインジェクトしたらよいかをフィールドの型によって判断します。ここではComponentResources型です。
以下の型がリソースインジェクションをサポートしています:
ある特定のオブジェクトを要求するには、 Serviceアノテーションを用いてサービス名を指定します。
例:
@Inject @Service("Request") private Request request;
通常これは必要ありません; インジェクトするサービスの特定は常に、明示的なIDの指定によるものでなく単に型によってできるべきです。 明示的なIDはリファクタリング時に安全ではないという欠点があります: もしサービスインターフェースの名前を変更しサービスIDもそれに合わせて変更したなら、 (そのような変更はRequestサービスにおいては起こることは無いはずです。しかし、あなた自身が作成した独自のサービスでは...) 明示的なサービスIDの指定による既存のインジェクションは壊れてしまうでしょう。
インジェクトするサービスやオブジェクトを特定するのにフィールドの型やその他のアノテーションだけでは不十分な場合、Tapestryは残りの2つの方法を実行します。 その場合、サービスのインターフェースによってサービスを特定するためにフィールドの型を用います。
ひとつ目は、Aliasサービスによって生成されるオブジェクトプロバイダを調べます。 オブジェクトプロバイダは、複数のサービスが同じサービスインターフェースを実装しているときの曖昧さをなくすために使用します。
ふたつ目は、フィールドのインターフェースを実装している唯一のサービスを探します。 これは、そのインターフェースを実装しているサービスがひとつも無い場合や、複数のサービスが実装している場合には失敗します。 後者の場合、Aliasサービスをcontributionするか、@Serviceアノテーションでサービスを明示的に指定して、曖昧さを回避しなければなりません。
匿名インジェクションはInjectionProviderサービスによって制御されています。 このサービスはchain of commandによってコンポーネントへのインジェクションを扱っています。