変更可能性を最小にする
できる限りコンストラクタ注入を用いて不変オブジェクトを作成すべきである。 不変オブジェクトはシンプルで共有可能で組合せ可能である。 注入される型をこのパターンに従うようにしよう。
public class RealPaymentService implements PaymentService { private final PaymentQueue paymentQueue; private final Notifier notifier; @Inject RealPaymentRequestService( PaymentQueue paymentQueue, Notifier notifier) { this.paymentQueue = paymentQueue; this.notifier = notifier; } ...
上のクラスのすべてのフィールドはfinalであり、一つの@Injectアノテーション付のコンストラクタによって初期化される。 「Effective Java」(訳注:書籍)では不変性のほかのメリットについても言及されている。
メソッド・フィールドへの注入
しかし、コンストラクタ注入はいくつかの制限がある。
- オプショナルにすることができない(訳注:@Inject(optional=true)にはできない)
- Guiceによって作成されたオブジェクトでなければ(コンストラクタ引数として)使うことができない。これはいくつかのフレームワークにとって受容できない問題である。
- サブクラスはすべての依存(オブジェクトを引数として)super()を呼び出す必要がある。これはとても扱いにくい、特にベースクラスが変更される場合には。
Method injection is most useful when you need to initialize an instance that is not constructed by Guice. Extensions like AssistedInject
- and Multibinder use method injection to initialize bound objects.
フィールドインジェクションは最もコンパクトなシンタックスであり、スライドや例でよく用いられる。 しかし、カプセル性も無いしテスト容易性も無い。 finalフィールドには絶対に注入しないこと。この場合、JVMは注入された値がすべてのスレッドから見えることを保証していない。