1. test 1
  2. test 2
  3. test 3
  4. test 4
コース一覧
Spring Boot入門
自作のDIコンテナ

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分

自作のDIコンテナ

このレッスンでは、DI コンテナの正体がとても素朴な対応表であることを、自分で書いて確かめられるようになります。

ApplicationContext は巨大な連想配列です

Spring の ApplicationContext は、名前と型からインスタンスを引ける対応表だと考えると、ほとんど正しく理解できます。起動時にコンポーネントスキャンと @Bean メソッドの実行で表を埋め、あとは要求に応じて引くだけです。

Java

ApplicationContext ctx = SpringApplication.run(Application.class, args); OrderService service = ctx.getBean(OrderService.class);

getBean がやっているのは、表から引いて返すことです。魔法があるとすれば、表を埋める過程のほうにあります。

表を埋めるときに再帰が起きます

OrderService を作るには Sender が要り、Sender の実装が Config を必要とするなら、先に Config を作らなければなりません。つまり生成の手順は次のようになります。

  1. 要求された型のコンストラクタを見る
  2. 引数の型を1つずつ取り出す
  3. その型の Bean をまだ作っていなければ、同じ手順で作りにいく
  4. 全部そろったらコンストラクタを呼ぶ
  5. できたインスタンスを表に入れる

3の「同じ手順で作りにいく」が再帰です。依存の木を葉から根に向かって解決していきます。前のレッスンで見た循環依存が起動時に検出できるのは、この再帰の途中で「いま作っている最中の型をもう一度作ろうとしている」と分かるからです。

一度作ったら使い回します

5で表に入れているのが効いています。次に同じ型が要求されたときは、生成の手順に入らず表から返します。この「一度だけ作って共有する」振る舞いが、既定のスコープである singleton の正体です。次のレッスンで扱います。

コンテナの仕事実体
Bean の登録対応表への put
Bean の取得対応表からの get
依存の解決引数の型を辿る再帰
singleton生成済みなら表から返す

Spring はどこで型を知るのか

Spring は実行時にリフレクションでコンストラクタの引数の型を読み取ります。この講座の実行環境ではリフレクションを使う複雑な処理までは組み立てられないので、演習では「名前で登録して名前で取り出す」形に単純化します。型による解決も、内部では同じ表を型で引いているだけです。

Java

// Spring の getBean の 2 つの入口 ctx.getBean("orderService"); // 名前で引く ctx.getBean(OrderService.class); // 型で引く

名前で引く場合、既定の名前はクラス名の先頭を小文字にしたものになります。@Bean メソッドで登録したものはメソッド名が名前になります。型で引く場合、その型に代入できる Bean が2つ以上あると、どれを返せばよいか決まらないので例外になります。前のレッスンで触れた @Primary や @Qualifier は、この曖昧さを解くための道具でした。表を引くという単純な仕組みだからこそ、鍵が重複したときの扱いを人間が決めてやる必要がある、と考えると腑に落ちます。

起動時にまとめて作られます

singleton の Bean は、最初に必要になった時点ではなく、コンテナの起動時にまとめて生成されます。設定の書き間違いや依存の欠落を、リクエストが来る前に洗い出すためです。起動が数秒かかる代わりに、起動さえ通れば依存関係は全部そろっていることが保証されます。あとから遅らせたい場合に @Lazy を付けます。

演習で書くこと

Map を内側に持つ小さなコンテナを実装します。名前でインスタンスを登録し、名前で取り出し、取り出したものを使って処理した結果を返します。ここまで書ければ、ApplicationContext に対して抱いていた漠然とした畏れは、かなり小さくなるはずです。

要件

  1. Container は内部に Map を持ち、register と getBean の 2 つのメソッドを持つこと
  2. getBean は未登録の名前に対して null を返すこと
  3. run は en / ja / fr の 3 つを登録したうえで名前で引き、未登録なら NoSuchBeanDefinition: xxx を返すこと

入出力例

run("en", "taro") → "Hello, taro" run("ja", "taro") → "こんにちは taro" run("fr", "hanako") → "Bonjour, hanako" run("de", "taro") → "NoSuchBeanDefinition: de"

ヒント

Map<String, Greeter> を Container のフィールドに持ち、register は put、getBean は get を呼ぶだけです

Greeter の実装はラムダで書けます。c.register("en", w -> "Hello, " + w); のような形です

getBean の戻り値が null かどうかを run で確かめてから greet を呼びます

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

関連レッスン

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

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

  • RESTという設計方針

    リソースと操作から URL とメソッドを導けるようになります。

  • JSONとオブジェクトの往復

    キーと値の対応づけを自分で実装し、変換の中身を掴みます。

  • 3層アーキテクチャ

    層を分ける理由と、それぞれの責務を説明できるようになります。

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

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

  • コンテナデータ取得や状態を担う上位コンポーネント
  • 配列サイズ固定の同型データの集まり
  • インスタンスクラスから生成された実体
  • コンポーネントUI を構成する再利用可能な部品
  • メソッドクラスに属する関数
  • 再帰関数が自分自身を呼び出す処理パターン
  • コンストラクタインスタンス生成時の初期化処理
  • 引数位置引数=順番で渡す。
main.java
学習モード
エディタを読み込んでいます

メモ

自作のDIコンテナ

⌘S で保存