Spring IoCコンテナにおけるBeanの遅延初期化戦略

コンテナ起動時のリソース最適化

SpringフレームワークのIoCコンテナは、デフォルト設定においてアプリケーションの起動フェーズで設定ファイルを読み込み、シングルトン定義のBeanをすべてインスタンス化して内部キャッシュへ登録します。小規模なプロジェクトではこの挙動に問題はありませんが、Beanの定義数が増加すると起動時間の遅延とメモリの過剰消費を招きます。特に、特定のユーザー操作やバッチ処理でのみ使用されるオブジェクトまで起動時に生成されるのは、システムリソースの非効率な利用につながります。

この課題を解決するため、Springは遅延初期化(Lazy Initialization)の仕組みを提供しています。この機能を有効化すると、指定されたBeanはコンテナ起動時ではなく、アプリケーションから初めて参照要求が発行されたタイミングで実際に生成されます。これにより、起動時のCPU負荷とヒープメモリ使用量を大幅に削減できます。なお、この制御はシングルトンスコープのBeanにのみ適用され、プロトタイプスコープのBeanは要求ごとに新規生成される仕様であるため、遅延初期化の設定自体が無効となります。

設定方式の使い分け

XMLベースの設定では、以下の2つの粒度で初期化タイミングを制御できます。

個別Beanへの設定

対象のBean定義に属性を追加することで、特定のオブジェクトのみ遅延生成を適用します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="inventoryManager" class="com.example.core.InventoryManager" lazy-init="true" />
</beans>

コンテナ全体への設定

ルート要素に属性を付与することで、コンテナ配下のすべてのBeanに対してデフォルト動作として遅延初期化を適用します。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-lazy-init="true">

    <bean id="reportGenerator" class="com.example.core.ReportGenerator" />
</beans>

両方の設定が同時に定義されている場合、Bean個別の設定が優先され、グローバルなデフォルト値を上書きします。

動作検証コード

以下の実装例を用いて、コンテキスト読み込み時と初回取得時のインスタンス生成タイミングを確認します。

package com.example.model;

public class DataExporter {
    public DataExporter() {
        System.out.println("[Lifecycle] DataExporter constructor invoked.");
    }

    public String export(String format) {
        return "Exported data in " + format;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-lazy-init="true">

    <bean id="exporter" class="com.example.model.DataExporter" />
</beans>
package com.example.test;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

class LazyInitIntegrationTest {

    @Test
    void verifyDeferredInstantiation() {
        System.out.println("=== Step 1: Context Loading ===");
        ApplicationContext container = new ClassPathXmlApplicationContext("app-context.xml");
        System.out.println("Context initialized successfully.\n");

        System.out.println("=== Step 2: First Bean Retrieval ===");
        DataExporter instanceA = container.getBean("exporter", DataExporter.class);
        System.out.println("Bean reference obtained.\n");

        System.out.println("=== Step 3: Singleton Verification ===");
        DataExporter instanceB = container.getBean("exporter", DataExporter.class);
        System.out.println("Instance equality: " + (instanceA == instanceB));
    }
}

タグ: spring-framework bean-lifecycle lazy-initialization xml-configuration ioc-container

9月9日 02:35 投稿