SpringでDIコンテナの管理対象となったインスタンスをインジェクション(注入)する3つの方法をメモしておきます。
コンストラクタインジェクション
コンストラクタを利用したDIで、最も推奨されるDIの方法です。
メリット
- フィールドをfinal化できる
- テスト時にモックオブジェクトに置き換えやすい
- Spring Frameworkを使用しないテストでも引数にモックを渡せる
デメリット
- 依存するBeanが増えるにつれて引数が多くなる(クラスの責務の多さに気づける)
- 循環依存A<->Bの場合は利用できない(循環依存に気づける)
残りの2つのインジェクション方法とは異なり、フィールドをfinal化できたりテストがしやすかったりするのが特徴です。デメリットにあげている点も裏を返せばメリットになります。Springチームが推奨しているインジェクション方法なので、基本的にはこのインジェクション方法を使うようにしましょう。
ちなみに、LomBokを使用すると、以下のようにコードが簡潔に書けます。
フィールドインジェクション
フィールドに直接@Autowired
を付与してDIする方法です。
メリット
- 簡潔に書ける
デメリット
- フィールドをfinal化できない
- テスト時にモックオブジェクトに置き換えできない(置き換えづらい)
なんといってもコードを簡潔に書けるが特徴です。ただ、SpringのDIコンテナを使用することが前提になるので、テストコード作成時にDIコンテナを使わないとモック化できなかったり、テスト時のコンテナ起動に時間がかかったりします。あと、フィールドをfinal化できないのもデメリットですね。
セッターインジェクション
setterを利用してDIする方法です。
メリット
- テスト時にモックオブジェクトに置き換えやすい
デメリット
- 依存するBeanが多いとsetterが多くなる
- フィールドをfinalにできない
- 外部からフィールドを上書きできる
コンストラクタインジェクションはコンストラクタ呼び出し時にDIの設定が完了(それ以降、不変)するのに対し、セッターインジェクションはsetterを利用するので書き換えが起こりえます。ということもあり、他の2つのインジェクション方法と異なり、あまり使われていない印象です。
まとめ
Spring FrameworkでDIする方法は以下の3つです。
- コンストラクタインジェクション
- フィールドインジェクション
- セッターインジェクション
基本的には推奨されているコンストラクタインジェクションを使うようにしましょう。