原文:IBM Developer : Sorry, that page no longer exists
訳1:Guice2.0 beta 紹介記事の翻訳(1) - 山本大の日記
訳2:Guice2.0 beta 紹介記事の翻訳(2) - 山本大の日記
インジェクションの別のやり方(Other forms of injection)
ここまでで、私は@Injectをコンストラクタに適用する方法を紹介しました。このアノテーションを見つけたら、
Guiceはコンストラクタ引数のそれぞれに設定されたバインディングを当てはめられないかを調べます。
これはコンストラクタインジェクションとして知られています。
Guiceのベストプラクティスガイドによると、コンストラクタインジェクションは
依存性を問い合わせるのにおすすめな方法です。しかし、その方法だけというわけではありません。
リスト9はFrogManクラスに設定するための別の方法を紹介しています。
リスト 9. メソッドインジェクション (Method injection)
public class FrogMan{ private Vehicle vehicle; @Inject public void setVehicle(Vehicle vehicle) { this.vehicle = vehicle; } //etc. ...
If you think Guice's decision to access private methods seems intrusive, wait until you see Listing 10, in which FrogMan uses field injection
インジェクトしたコンストラクターを取り除いた代わりに@Injectアノテーションでタグ付けされたメソッドがあることに注意して下さい。Guiceはヒーローを構築した後、即座にこのメソッドを呼び出します。Spring Frameworkの愛好者はこれを"セッターインジェクション"と見るでしょう。しかしながら、Guiceは@Injectについてのみ扱います。つまり、対象とするメソッドでは何でも好きな名前を付けてもよく、さらに複数パラメータをとることもできます。パッケージプロテクテッドやプライベートなメソッドでも同様です。
もし、プライベートメソッドにアクセスするというGuiceの決定を信用できないと思ったとしても、リスト10を見るまでは待ってください。ここではFrogManがフィールドインジェクションを使っています。
リスト10. フィールドインジェクション(Field injection)
public class FrogMan { @Inject private Vehicle vehicle; public FrogMan(){} //etc. ...
ここでも結局、Guiceは@Injectアノテーションについてしか扱いません。Guiceはアノテートされたフィールドを見つけ、適切な依存性を注入しようと試みます。
どっちが良いの? (Which one is best?)
3つのバージョンのFrogManは、同じ振る舞いをしているように見えます。Guiceはインスタンス構築時に適切な乗り物(Vehicle)をインジェクトします。しかしながら、私はGuiceの作者と同じく、コンストラクタインジェクションをおすすめします。以下に、3つのスタイル毎の簡単な分析を述べます。
- Constructor injection is straightforward. Because Java technology guarantees constructor invocation, you don't need to worry about objects arriving in an uninitialized state ― whether or not Guice creates them. You can also mark your fields final.
- Field injection harms testability, especially if you mark the fields private. That defeats one of the main aims of DI. You should use field injection only in very limited circumstances.
- Method injection can be useful if you don't control a class's instantiation. You can also use it if you have a superclass that needs some dependencies. (Constructor injection makes this difficult.)
- コンストラクタインジェクションは、正統なやり方です。なぜなら、Java技術ではコンストラクタによる初期化を推奨しているからです。Guiceで生成していなくても同じことが言えるのですが、コンストラクタによってオブジェクトを生成することでオブジェクトが正しく初期化されていない状態で生存しているかもしれないという心配がなくなります。また、この方法であればフィールドにFilanlの修飾子をつけることが可能です。
- フィールドインジェクションは、テストしやすさを阻害します。特に、フィールドをプライベートにしたときには顕著です。これはDIの主な目的の一つを駄目にします。そのためフィールドインジェクションはかなり限られた状況でのみ利用すべきです。
- メソッドインジェクションは、クラスのインスタンス化をコントロールできない場合に便利です。また、いくつかの依存性を必要とするスーパークラスにも使えます。(コンストラクターインジェクションではこれは難しい作業です。)