可能であればいつでも、不変なオブジェクトを生成するようにコンストラクターインジェクションを使用すること。不変なオブジェクトはシンプルで、共有でき、再利用できる。このパターンにしたがって注入可能なクラスを定義する。
このクラスの全てのフィールドはfinalであり、@Injectが付けられたコンストラクタで初期化されている。Effective Javaでは不変性の他の利点について述べられている。
メソッドインジェクションとフィールドインジェクション
コンストラクターインジェクションにはいくつかの制限がある。
public class RealPaymentService implements PaymentService { private final PaymentQueue paymentQueue; private final Notifier notifier; @Inject RealPaymentService( PaymentQueye paymentQueue, Notifier notifier) { this.paymentQueue = paymentQueue; this.notifier = notifier; } ...
このクラスの全てのフィールドはfinalであり、@Injectが付けられたコンストラクタで初期化されている。Effective Javaでは不変性の他の利点について述べられている。
メソッドインジェクションとフィールドインジェクション
コンストラクターインジェクションにはいくつかの制限がある。
- 注入されるコンストラクタはオプションにならない。
- オブジェクトがGuiceによって生成されない限り、使用されない。これは一部のフレームワークとの関係を断つ。
- サブクラスはsuper()を全ての依存するクラスとともに呼ばなければならない。これはコンストラクターインジェクションを扱いにくくする。親クラスに変更があったときは特に。
Guiceによって生成されないオブジェクトを初期化するなら、メソッドインジェクションがもっとも便利だ。AssistedInjectやMultibinderのような拡張は、バインドされたオブジェクトを初期化するために、メソッドインジェクションを使用する。
フィールドインジェクションは、コンパクトに記述できる。故に、例を示すときやスライドで頻繁に目にする。それはカプセル化もできていないし、テストもしにくい。finalなフィールドへ注入してはいけない。注入された値が全てのスレッドで参照できることを、JVMは保証していない。