1. test 1
  2. test 2
  3. test 3
  4. test 4
コース一覧
Spring Boot入門
コンストラクタインジェクション

Spring Boot入門

Java で Web API サーバーを作るための Spring Boot の入門コースです。DI コンテナ、REST コントローラ、リクエスト検証、レイヤ分割、Spring Data JPA、例外ハンドリング、テストまでを扱います。毎レッスン、Spring が裏側でやっている判断そのものを pure Java の関数として自分で書き、フレームワークが何を肩代わりしてくれているのかを手触りで理解できる構成にしました。約 12 時間 (1 日 30 分 × 24 日) で 48 レッスンを修了できます。

1
Spring Bootとは何か
01. Spring Bootで何が作れるのか10分
02. サーブレットからフレームワークへ15分
03. ルーティング表という発想15分
04. プロジェクトの構成10分
05. 起動のしくみと自動設定15分
06. パスのマッチング15分
2
DIコンテナ
01. newで書くと何が困るのか15分
02. コンストラクタインジェクション15分
03. インターフェースへの依存15分
04. @Componentと@Bean15分
05. 自作のDIコンテナ20分
06. Beanのスコープとライフサイクル15分
3
RESTコントローラ
01. RESTという設計方針15分
02. @RestControllerの役割15分
03. @GetMappingとパス変数15分
04. クエリパラメータの受け取り15分
05. @PostMappingとリクエストボディ15分
06. ステータスコードの選び方15分
07. ResponseEntityで組み立てる15分
4
リクエストとレスポンスの変換
01. JSONとオブジェクトの往復15分
02. DTOとエンティティを分ける15分
03. recordでDTOを書く15分
04. 入力検証の基本15分
05. 検証エラーをまとめて返す15分
06. アノテーションによる検証15分
5
レイヤ構成とビジネスロジック
01. 3層アーキテクチャ10分
02. @Serviceに置くもの15分
03. 状態遷移をルールにする15分
04. 料金計算のような業務ロジック15分
05. @Transactionalとは何か15分
06. トランザクションの巻き戻し15分
6
データアクセス
01. @Entityとテーブルの対応15分
02. リポジトリという抽象15分
03. メソッド名からクエリを作る20分
04. 検索条件の組み立て15分
05. ページングと並び替え15分
06. N+1問題15分
7
例外処理と横断的関心事
01. 例外をHTTPに変換する15分
02. @ExceptionHandlerと@ControllerAdvice15分
03. エラーレスポンスの形を決める15分
04. フィルタとインターセプタ15分
05. ログとリクエストの追跡15分
06. 設定値の外部化15分
8
テストと仕上げ
01. テストの種類と使い分け15分
02. Serviceの単体テスト15分
03. モックで依存を差し替える15分
04. MockMvcでエンドポイントを試す15分
05. 本番へ出すための次の一歩10分

コンストラクタインジェクション

このレッスンでは、依存を受け取る3つの書き方を比べ、なぜコンストラクタインジェクションが推奨されるのかを説明できるようになります。

注入には3つの入口があります

Spring が依存を渡す経路は3種類あります。

Java

// 1. フィールドインジェクション @Service class OrderService { @Autowired private Sender sender; } // 2. セッターインジェクション @Service class OrderService { private Sender sender; @Autowired void setSender(Sender sender) { this.sender = sender; } } // 3. コンストラクタインジェクション (推奨) @Service class OrderService { private final Sender sender; OrderService(Sender sender) { this.sender = sender; } }

3番目が推奨されます。しかも Spring Boot では、コンストラクタが1つしかないクラスであれば @Autowired を書く必要すらありません。理由を1つずつ見ていきます。

理由1 final にできます

コンストラクタで受け取った値だけが final フィールドに入れられます。フィールドインジェクションではリフレクションで後から値が差し込まれるため、final は付けられません。final が付くと、生成のあとで依存がすり替わらないことがコンパイラによって保証されます。マルチスレッドで共有される singleton の Bean にとって、これは地味に効きます。

理由2 必須の依存が引数として見えます

コンストラクタの引数リストは、そのクラスが動くために何が要るのかの一覧そのものです。引数が6個も7個もあるなら、そのクラスは責務を持ちすぎているという設計上の警告になります。フィールドインジェクションではフィールドが何個増えても引数リストは膨らまないので、この警告灯が点きません。

理由3 テストで素直に差し替えられます

コンストラクタがあれば、テストコードは Spring を起動せずに new OrderService(fakeSender) と書くだけで済みます。フィールドインジェクションだと、依存を差し込む手段がリフレクションかテスト用フレームワークの助けしかありません。「素の Java として組み立てられる」という性質が、そのままテストの書きやすさになります。

理由4 循環依存が起動時に分かります

A が B を必要とし、B も A を必要とする状態を循環依存と呼びます。コンストラクタインジェクションでは、どちらを先に作ることもできないので、アプリケーションの起動時点で失敗します。フィールドインジェクションだと空のインスタンスを先に作って後から差し込めてしまうため、起動は通り、実行時になって初めておかしくなります。壊れているなら早く壊れてほしいというのが設計判断の要点です。

書き方final必須依存が見えるSpring 無しでテスト循環依存の発覚
フィールド不可見えにくい面倒実行時
セッター不可任意扱い可能実行時
コンストラクタ可引数で明示容易起動時

セッターインジェクションが役に立つのは、依存が任意である場合や、あとから差し替える余地を意図的に残したい場合に限られます。

Lombok の @RequiredArgsConstructor

実務では final フィールドを並べて @RequiredArgsConstructor を付け、コンストラクタを自動生成させる書き方もよく見ます。生成されるのは普通のコンストラクタなので、上の利点はそのまま保たれます。

演習で書くこと

2つの実装を持つインターフェースを用意し、コンストラクタで受け取る Service を書きます。渡した実装によって結果が変わることを、返り値で確かめます。

要件

  1. DiscountPolicy インターフェースと NoneDiscount / RateDiscount の 2 実装を作ること
  2. PriceService は DiscountPolicy をコンストラクタで受け取り、final フィールドに保持すること
  3. run は policy 名と支払額を rate:900 の形で連結して返し、未知の policy では unknown を返すこと

入出力例

run("none", 1000) → "none:1000" run("rate", 1000) → "rate:900" run("rate", 2500) → "rate:2250" run("cash", 1000) → "unknown"

ヒント

10 パーセントは price / 10 で求まります。int どうしの割り算なので自動的に切り捨てになります

支払額は price から割引額を引いた値です

文字列の連結は policy + ":" + pay のように書けます

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/08/09

関連レッスン

  • インターフェースへの依存

    実装ではなく契約に依存させ、差し替え可能にします。

  • @Componentと@Bean

    Bean 登録の 2 つの方法の使い分けを確認します。

  • 自作のDIコンテナ

    型から実装を引く小さなコンテナを実装します。

  • Beanのスコープとライフサイクル

    singleton と prototype で生成回数が変わることを実装で確かめます。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • コンストラクタインスタンス生成時の初期化処理
  • クラスデータと振る舞いを束ねる単位
  • フィールドクラスが持つデータ
  • スレッド1 つの質問に紐づく返信の集まり
  • 引数位置引数=順番で渡す。
  • リスト順序付きで複数の値を扱うデータ構造
  • 設計何をどう作るかを決める前工程
  • テストバグを見つける工程
main.java
学習モード
エディタを読み込んでいます

メモ

コンストラクタインジェクション

⌘S で保存