1. test 1
  2. test 2
  3. test 3
  4. test 4
コース一覧
Spring Boot入門
newで書くと何が困るのか

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分

newで書くと何が困るのか

このレッスンでは、クラスの中で直接 new を書いてしまうと何が困るのかを、自分の手で確かめられるようになります。

まずは素朴に書いてみます

注文が確定したときに、ユーザーへ通知を送る処理を考えます。素直に書くと次のようになります。

Java

class MailSender { String send(String to, String body) { return "mail to " + to + " / " + body; } } class OrderService { private final MailSender sender = new MailSender(); // ここが問題 String complete(String user) { return sender.send(user, "order completed"); } }

動きます。動きますが、この OrderService はもう MailSender から離れられません。

困りごとは3つあります

1つめは差し替えができないことです。 「メールではなく SMS で送りたい」という要望が来たとき、OrderService のソースコードを開いて new MailSender() を new SmsSender() に書き換えるしかありません。呼び出し側がどれだけ増えても、切り替えの主導権は OrderService の内部にあります。

2つめはテストが書けないことです。 complete をテストしたいだけなのに、実行すると本物の MailSender が動きます。もし本当にメールを送る実装だったら、テストを走らせるたびにメールが飛びます。テスト用の偽物に差し替えたくても、OrderService の中で new しているので外から手が出せません。

3つめは組み立ての知識が散らばることです。 MailSender が SMTP のホスト名を必要とするようになったら、OrderService がその設定値を知らなければなりません。本来 OrderService の関心事ではない設定が、業務ロジックのクラスに染み出してきます。

誰が誰を作るのか、という一点

3つの困りごとは、すべて同じ原因から来ています。使う側が、使われる側を自分で作っているという点です。

書き方依存の向き差し替え
中で new する使う側が実装クラスを名指しする不可
外から受け取る使う側は型だけを知る可能

作る責任を外に追い出せば、OrderService は「送れる何か」を受け取って使うだけの存在になります。この「作る責任を外に出す」考え方が、次のレッスンで扱う依存性注入 (Dependency Injection) です。

Spring は何をしてくれるのか

Spring では、この「外から渡す」役を DI コンテナが引き受けます。

Java

@Service class OrderService { private final Sender sender; OrderService(Sender sender) { // 誰が渡すかは書かない this.sender = sender; } }

new OrderService(...) を書く場所はアプリケーションのどこにもありません。起動時にコンテナが Sender の実装を見つけ、コンストラクタに流し込んでくれます。差し替えたいときは、渡す実装を変えるだけです。OrderService のソースコードは1文字も変わりません。

ただし、この講座の実行環境では Spring のコンテナそのものは動きません。そこで演習では、コンテナが裏側でやっている「どの実装を使うか決める」という判断を、自分の手で書きます。

演習で書くこと

通知手段を表す文字列を受け取り、対応する実装を選んで送信結果を返す関数を書きます。new を1か所に閉じ込め、OrderService 自身は実装の名前を知らない形にするのがねらいです。

要件

  1. Sender インターフェースを作り、MailSender と SmsSender の 2 実装を用意すること
  2. OrderService は Sender をコンストラクタで受け取り、内部で new しないこと
  3. run は kind に応じて実装を選び、mail to taro / sms to taro のような文字列を返し、未知の kind では unknown を返すこと

入出力例

run("mail", "taro") → "mail to taro" run("sms", "taro") → "sms to taro" run("sms", "hanako") → "sms to hanako" run("fax", "taro") → "unknown"

ヒント

public class Main の中に interface Sender { String send(String user); } を書けます

実装は static class MailSender implements Sender { ... } の形で並べます

run の中で Sender s = ...; と選び分けてから new OrderService(s).complete(user) を呼びます

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

関連レッスン

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

    依存を外から渡す形に組み替えられるようになります。

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

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

  • @Componentと@Bean

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

  • 自作のDIコンテナ

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

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

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

  • クラスデータと振る舞いを束ねる単位
  • 処理計算や代入を表す長方形
  • テストバグを見つける工程
  • コンテナデータ取得や状態を担う上位コンポーネント
  • コンストラクタインスタンス生成時の初期化処理
  • 判断YES/NO 分岐を表す菱形
  • 関数処理に名前を付けて再利用できる単位
  • インターフェースインターフェースはメソッドの宣言のみ(実装なし)、複数実装可能。
main.java
学習モード
エディタを読み込んでいます

メモ

newで書くと何が困るのか

⌘S で保存