1. test 1
  2. test 2
  3. test 3
  4. test 4
  5. test 5
  6. test 6
コース一覧
Spring Boot入門
Beanのスコープとライフサイクル

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分

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

このレッスンでは、Bean のスコープによってインスタンスがいくつ作られるのかを、実装で確かめられるようになります。

既定は singleton です

Spring の Bean は、何も指定しなければ singleton スコープになります。コンテナの中にインスタンスが1つだけ作られ、必要とするすべての場所へ同じインスタンスが渡されます。

Java

@Service class OrderService { } // コンテナ内に 1 つだけ

OrderService を注入しているクラスが10個あっても、渡される OrderService は同じものです。生成の回数が減るので効率がよく、状態を持たないクラスであれば何の問題もありません。

ここで言う singleton は、GoF のシングルトンパターンとは別物です。パターンのほうは JVM 全体で1つですが、Spring の singleton はコンテナごとに1つという意味です。同じアプリケーションの中に複数のコンテナを立てれば、その数だけインスタンスができます。

prototype は取得のたびに作られます

@Scope("prototype") を付けると、コンテナから取得するたびに新しいインスタンスが作られます。

Java

@Component @Scope("prototype") class ShoppingCart { } // getBean のたびに新品

利用者ごとに状態を持つオブジェクトや、使い捨てのオブジェクトに向いています。

スコープ生成のタイミングインスタンス数
singleton (既定)コンテナの起動時コンテナに1つ
prototype取得のたび取得回数と同じ
requestHTTP リクエストごとリクエスト数と同じ
sessionHTTP セッションごとセッション数と同じ

request と session は Web アプリケーションでのみ使えるスコープです。

singleton が共有されるという事実

ここが実務でいちばん事故を生む点です。singleton の Bean は複数のスレッドから同時に呼ばれます。もしフィールドに状態を持たせていると、あるリクエストの処理中に別のリクエストがその値を書き換えてしまいます。

Java

@Service class CounterService { private int count; // 全リクエストで共有される void add() { count++; } // 競合する }

このため、Service や Repository は状態を持たないように書くのが原則です。リクエストごとに変わる値はフィールドではなくメソッドの引数とローカル変数で持ち回ります。前のレッスンでコンストラクタインジェクションと final を勧めたのも、この原則と地続きです。

prototype を singleton に注入するときの注意

singleton の Bean が prototype の Bean を注入して保持すると、注入は最初の1回しか起きないので、結局そのインスタンスがずっと使い回されます。毎回新しいものが欲しければ、ObjectProvider を注入して必要なときに取得するなど、取得の側を工夫する必要があります。スコープは「注入された相手が自動で更新される」仕組みではない、と覚えておいてください。

演習で書くこと

スコープ名と取得回数を受け取り、実際に生成されたインスタンスが何個になるかを返します。singleton なら常に1、prototype なら取得回数と同じになるはずです。コンテナが裏でやっている「作るか、取っておいたものを返すか」の分岐を、自分の手で書きます。

要件

  1. Cart は生成のたびに静的なカウンタを 1 増やすこと。run の先頭でカウンタを 0 に戻すこと
  2. ScopedContainer の getBean は singleton なら保持したインスタンスを返し、prototype なら毎回 new すること
  3. run は singleton:1 / prototype:3 のような文字列を返し、未知のスコープでは unknown scope を返すこと

入出力例

run("singleton", 3) → "singleton:1" run("prototype", 3) → "prototype:3" run("singleton", 1) → "singleton:1" run("prototype", 5) → "prototype:5" run("singleton", 0) → "singleton:0" run("request", 3) → "unknown scope"

ヒント

Cart のコンストラクタの中で created++ と書けば、生成回数を数えられます

singleton の判定は、保持しているフィールドが null かどうかで書けます

テストごとに状態が残らないよう、run の先頭で Cart.created = 0; を実行してください

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

関連レッスン

  • RESTという設計方針

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

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

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

  • 3層アーキテクチャ

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

  • @Entityとテーブルの対応

    エンティティのマッピングと主キーの指定を確認します。

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

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

  • スコープ変数が参照可能な範囲
  • インスタンスクラスから生成された実体
  • コンテナデータ取得や状態を担う上位コンポーネント
  • クラスデータと振る舞いを束ねる単位
  • オブジェクトキーと値のペアで構造を作るデータ
  • HTTPWeb の通信プロトコル、HTTPS は TLS で暗号化したもの
  • リクエストWeb 通信の基本単位、ブラウザの問い合わせとサーバーの返答
  • セッションブラウザごとに紐づくサーバー側の保管箱
main.java
学習モード
エディタを読み込んでいます

メモ

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

⌘S で保存