1. 概要

このチュートリアルでは、 Spring Boot 2.2。から始めて、アプリケーションレベルで遅延初期化を構成する方法を説明します。

2. 怠惰な初期化

Springのデフォルトでは、定義されたすべてのBeanとその依存関係は、アプリケーションコンテキストの作成時に作成されます。

対照的に、レイジー初期化を使用してBeanを構成すると、 Beanは、必要になったときにのみ作成され、その依存関係が注入されます。

3. Mavenの依存関係

アプリケーションでSpringBootを取得するには、それをクラスパスに含める必要があります。

Mavenを使用すると、spring-boot-starter依存関係を追加できます。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <version>2.4.3</version>
    </dependency>
</dependencies>

4. 遅延初期化を有効にする

Spring Boot 2では、 spring.main.lazy-initialization プロパティが導入され、アプリケーション全体で遅延初期化を簡単に構成できるようになります。

プロパティ値をtrueに設定すると、アプリケーション内のすべてのBeanが遅延初期化を使用することになります。

application.yml構成ファイルでプロパティを構成しましょう。

spring:
  main:
    lazy-initialization: true

または、その場合は、application.propertiesファイルで次のようにします。

spring.main.lazy-initialization=true

この構成は、コンテキスト内のすべてのBeanに影響します。 したがって、特定のBeanのレイジー初期化を構成する場合は、@Lazyアプローチを使用して構成できます。

さらに、 @Lazy アノテーションと組み合わせて、falseに設定された新しいプロパティを使用できます。

つまり、定義されたすべてのBeanは、@ Lazy(false) で明示的に構成したものを除いて、レイジー初期化を使用します。

4.1. SpringApplicationBuilderを使用する

遅延初期化を構成する別の方法は、SpringApplicationBuilderメソッドを使用することです。

SpringApplicationBuilder(Application.class)
  .lazyInitialization(true)
  .build(args)
  .run();

上記の例では、 lazyInitialization メソッドを使用して、アプリケーションを遅延初期化するかどうかを制御します。

4.2. SpringApplicationを使用する

または、SpringApplicationクラスを使用することもできます。

SpringApplication app = new SpringApplication(Application.class);
app.setLazyInitialization(true);
app.run(args);

ここでは、 setLazyInitialization メソッドを使用して、アプリケーションを遅延初期化するように構成します。

覚えておくべき重要な注意点の1つは、アプリケーションプロパティファイルで定義されたプロパティは、SpringApplicationまたはSpringApplicationBuilderのいずれかを使用して設定されたフラグよりも優先されることです。

5. 走る

今説明したことをテストできる簡単なサービスを作成しましょう。

コンストラクターにメッセージを追加することで、Beanがいつ作成されるかを正確に知ることができます。

public class Writer {

    private final String writerId;

    public Writer(String writerId) {
        this.writerId = writerId;
        System.out.println(writerId + " initialized!!!");
    }

    public void write(String message) {
        System.out.println(writerId + ": " + message);
    }
    
}

また、 SpringApplication を作成して、前に作成したサービスを注入しましょう。

@SpringBootApplication
public class Application {

    @Bean("writer1")
    public Writer getWriter1() {
        return new Writer("Writer 1");
    }

    @Bean("writer2")
    public Writer getWriter2() {
        return new Writer("Writer 2");
    }

    public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(Application.class, args);
        System.out.println("Application context initialized!!!");

        Writer writer1 = ctx.getBean("writer1", Writer.class);
        writer1.write("First message");

        Writer writer2 = ctx.getBean("writer2", Writer.class);
        writer2.write("Second message");
    }
}

spring.main.lazy-initializationプロパティ値をfalseに設定して、アプリケーションを実行してみましょう。

Writer 1 initialized!!!
Writer 2 initialized!!!
Application context initialized!!!
Writer 1: First message
Writer 2: Second message

ご覧のとおり、Beanはアプリケーションコンテキストの起動時に作成されました。

次に、spring.main.lazy-initializationの値をtrueに変更して、アプリケーションを再実行してみましょう。

Application context initialized!!!
Writer 1 initialized!!!
Writer 1: First message
Writer 2 initialized!!!
Writer 2: Second message

その結果、アプリケーションは起動時にBeanを作成しませんでしたが、必要な場合にのみ作成しました。

6. 遅延初期化の影響

アプリケーション全体で遅延初期化を有効にすると、プラスとマイナスの両方の効果が生じる可能性があります。

新機能の公式発表と説明されているので、これらのいくつかについて話しましょう。

  1. 遅延初期化により、アプリケーションの起動時に作成されるBeanの数が減る可能性があります。したがって、アプリケーションの起動時間を改善できます。
  2. 必要になるまでBeanは作成されないため、問題をマスクして、起動時ではなく実行時に取得することができます
  3. 問題には、メモリ不足エラー、設定ミス、クラス定義で見つかったエラーなどがあります。
  4. また、Webコンテキストでは、オンデマンドでBeanの作成をトリガーすると、HTTPリクエストのレイテンシが増加します – Beanの作成は最初のリクエストにのみ影響しますが、これは悪影響を与える可能性があります負荷分散と自動スケーリングについて。

7. 結論

このチュートリアルでは、Spring Boot2.2で導入された新しいプロパティspring.main.lazy-initialization、を使用してレイジー初期化を構成しました。

いつものように、このチュートリアルのソースコードは、GitHubからで入手できます。