🧑‍💻 Spring Framework 講座【第10回】Beanの寿命と範囲!〜スコープとライフサイクルの管理〜

docs

前回は、業務システムの三層構造に対応する @Component 系のアノテーションを学び、Beanの役割を明確にしました。

今回は、Spring IoCコンテナが管理するBeanの「寿命」と「範囲」、すなわち「スコープ」と「ライフサイクル」について解説します。これらの概念は、アプリケーションのメモリ使用量やスレッド安全性(同時アクセス時の問題)に直結するため、業務システム設計において極めて重要です。

1. Beanのスコープとは?

スコープ (Scope) とは、「そのBeanのインスタンスが、いつ、いくつ生成されるか」を決定する範囲のことです。

Spring Frameworkにはいくつかのスコープがありますが、最も重要なのは「Singleton」と「Prototype」の2つです。

スコープ名意味動作Springでの推奨
Singletonコンテナ全体でたった一つのインスタンスを共有する。アプリケーションの起動時に一度だけ生成され、ずっと使い回される。デフォルトであり、ほとんどのBeanで利用すべき。
PrototypeDIや取得の要求があるたびに、新しいインスタンスを生成する。複数回要求すれば、その都度新しいオブジェクトが作られる。状態を持つBean、スレッドごとに独立させたい場合に利用。

1-1. Singleton(シングルトン)の適用

Spring Beanのデフォルトのスコープです。特別な理由がない限り、すべての @Service@Repository はSingletonとして定義されます。

メリット:

  • メモリの節約になります。
  • ほとんどのSpringのBeanは状態を持たない(ステートレス)ため、Singletonで安全に共有できます。

1-2. Prototype(プロトタイプ)の適用

Beanを使うたびに新しいインスタンスが必要な場合は、@Scope("prototype") を指定します。

Java

// 要求があるたびに新しいインスタンスが生成されるBean
@Component
@Scope("prototype")
public class TaskProcessor {
    // 状態を持つフィールド(例:このタスク固有の処理状況)
    private String currentTask; 
    
    public void start(String taskName) {
        this.currentTask = taskName;
        System.out.println("タスク " + taskName + " が開始されました。");
    }
}

Prototypeの注意点:

Prototype BeanはSpringが生成までは管理しますが、破棄(destroy)の管理は行いません。そのため、リソースの解放が必要な場合は、プログラマが手動で行う必要があります。

1-3. Webスコープ(Webアプリケーション特有)

Webアプリケーション開発(次回以降詳しく扱います)では、さらに以下のスコープが使われることがあります。

  • request: HTTPリクエストごとに新しいBeanが生成され、レスポンスが返ると破棄されます。
  • session: HTTPセッションごとに新しいBeanが生成され、セッションが終了すると破棄されます。

2. Beanのライフサイクル:生成から破棄までの道のり

Beanの「ライフサイクル」とは、IoCコンテナがBeanを生成してから、アプリケーションの終了などで破棄されるまでの過程のことです。

プログラマは、Beanの**「初期化(生成直後)」「破棄(終了直前)」**のタイミングで、特定の処理を実行できます。

2-1. 初期化処理 (Initialization)

Beanの全依存関係(DI)が注入され、オブジェクトが完全に準備できた直後に実行したい処理です。

例えば、初期データをロードしたり、外部リソースへの接続を確立したりする場合に使います。

アノテーションによる指定:

@PostConstruct アノテーションをメソッドに付けることで、初期化処理として指定できます。

Java

@Service
public class DataInitializer {
    
    // DIが完了した後(コンストラクタが実行された後)に呼ばれる
    @PostConstruct
    public void init() {
        System.out.println("【初期化処理】初期データをデータベースにロードします。");
        // 初期データロードなどの処理を記述
    }
}

2-2. 破棄処理 (Destruction)

アプリケーションが終了する際など、Beanがコンテナから破棄される直前に実行したい処理です。

例えば、開いたデータベース接続を閉じたり、メモリ上のキャッシュをクリアしたりする場合に使います。

アノテーションによる指定:

@PreDestroy アノテーションをメソッドに付けることで、破棄処理として指定できます。

Java

@Service
public class ResourceCloser {
    
    // Beanが破棄される直前(コンテナがシャットダウンされるとき)に呼ばれる
    @PreDestroy
    public void cleanup() {
        System.out.println("【破棄処理】データベース接続を安全に閉じます。");
        // リソース解放処理を記述
    }
}

3. Beanライフサイクルの流れ(Singletonの場合)

Singleton Beanのライフサイクルは、以下の順序で実行されます。

  1. インスタンス化: コンテナがJavaの new 演算子を呼び出し、Beanのオブジェクトを生成。
  2. 依存性の注入(DI): @Autowired などに基づき、必要な依存Beanを注入。
  3. 初期化: @PostConstruct が付いた初期化メソッドを実行。
  4. 利用: アプリケーション内で利用される。
  5. 破棄: コンテナが停止する際に、@PreDestroy が付いた破棄メソッドを実行。

✅ 本日のまとめ

  • スコープは、Beanのインスタンスがいくつ生成されるかを定義する。
  • Singleton(コンテナで一つ)がデフォルトであり、ほとんどの**ステートレス(状態を持たない)**なBeanに使用すべきである。
  • Prototype(要求ごとに新規)は、状態を持つBeanに使用する。
  • ライフサイクルにおいて、@PostConstruct初期化時に、@PreDestroy破棄時に実行する処理を指定する。

🔔 次回予告

これでSpring Coreの最も重要な概念である IoCコンテナ、DI、Beanの定義、スコープ を完全にマスターしました。

次回は、これまでアノテーションを使ってきたBean定義を、あえてJavaコードで記述する「Java Config」について学びます。これは、外部ライブラリのBeanを定義したり、Beanの生成ロジックを複雑にしたい場合に必須のテクニックです。

次回:【第11回】Java Configによる設定 にご期待ください!

コメント

タイトルとURLをコピーしました