プログラムによるSpring Bootアプリケーションの再起動

プログラムによるSpring Bootアプリケーションの再起動

1. 概要

このチュートリアルでは、programmatically restart a Spring Boot applicationを実行する方法を示します。

アプリケーションの再起動は、場合によっては非常に便利です。

  • いくつかのパラメーターの変更時に設定ファイルをリロードする

  • 実行時に現在アクティブなプロファイルを変更する

  • 何らかの理由でアプリケーションコンテキストを再初期化する

この記事ではSpringBootアプリケーションを再起動する機能について説明しますが、shutting down Spring Boot applicationsに関する優れたチュートリアルもあることに注意してください。

それでは、SpringBootアプリケーションの再起動を実装するさまざまな方法を見ていきましょう。

2. 新しいコンテキストを作成して再起動します

アプリケーションコンテキストを閉じて、ゼロから新しいコンテキストを作成することにより、アプリケーションを再起動できます。 このアプローチは非常に単純ですが、動作させるために注意しなければならない繊細な詳細がいくつかあります。

Spring Bootアプリのmainメソッドでこれを実装する方法を見てみましょう。

@SpringBootApplication
public class Application {

    private static ConfigurableApplicationContext context;

    public static void main(String[] args) {
        context = SpringApplication.run(Application.class, args);
    }

    public static void restart() {
        ApplicationArguments args = context.getBean(ApplicationArguments.class);

        Thread thread = new Thread(() -> {
            context.close();
            context = SpringApplication.run(Application.class, args.getSourceArgs());
        });

        thread.setDaemon(false);
        thread.start();
    }
}

上記の例でわかるように、別の非デーモンスレッドでコンテキストを再作成することが重要です。これにより、closeメソッドによってトリガーされるJVMのシャットダウンがアプリケーションを閉じるのを防ぐことができます。 そうしないと、JVMはデーモンスレッドが終了するのを待たずに終了するため、アプリケーションが停止します。

さらに、再起動をトリガーできるRESTエンドポイントを追加しましょう。

@RestController
public class RestartController {

    @PostMapping("/restart")
    public void restart() {
        Application.restart();
    }
}

ここでは、restartメソッドを呼び出すマッピングメソッドを備えたコントローラーを追加しました。

次に、新しいエンドポイントを呼び出してアプリケーションを再起動します。

curl -X POST localhost:port/restart

もちろん、このようなエンドポイントを実際のアプリケーションに追加する場合は、それも保護する必要があります。

3. アクチュエータの再起動エンドポイント

アプリケーションを再起動するもう1つの方法は、Spring Boot Actuator.から組み込みのRestartEndpointを使用することです。

まず、必要なMavenの依存関係を追加しましょう。


    org.springframework.boot
    spring-boot-starter-actuator


    org.springframework.boot
    spring-cloud-starter

次に、application.propertiesファイルで組み込みの再起動エンドポイントを有効にする必要があります。

management.endpoint.restart.enabled=true

すべての設定が完了したので、サービスにRestartEndpoint を挿入できます。

@Service
public class RestartService {

    @Autowired
    private RestartEndpoint restartEndpoint;

    public void restartApp() {
        restartEndpoint.restart();
    }
}

上記のコードでは、RestartEndpoint beanを使用してアプリケーションを再起動しています。 これは、すべての作業を行う1つのメソッドを呼び出すだけでよいため、再起動するのに便利な方法です。

ご覧のとおり、RestartEndpointを使用すると、アプリケーションを再起動する簡単な方法です。 一方、このアプローチには欠点があります。これは、前述のライブラリを追加する必要があるためです。 まだ使用していない場合は、この機能だけではオーバーヘッドが大きすぎる可能性があります。 その場合、必要なコードはわずか数行なので、前のセクションの手動アプローチに固執することができます。

4. アプリケーションコンテキストの更新

場合によっては、refreshメソッドを呼び出すことでアプリケーションコンテキストをリロードできます。

この方法は有望に聞こえるかもしれませんが、一部のアプリケーションコンテキストタイプのみが、既に初期化されたコンテキストの更新をサポートしています。 たとえば、FileSystemXmlApplicationContextGroovyWebApplicationContext,などがサポートしています。

残念ながら、Spring Boot Webアプリケーションでこれを試みると、次のエラーが表示されます。

java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts:
just call 'refresh' once

最後に、複数の更新をサポートするコンテキストタイプがいくつかありますが、これは避けてください。 その理由は、refreshメソッドが、アプリケーションコンテキストを初期化するためにフレームワークによって使用される内部メソッドとして設計されているためです。

5. 結論

この記事では、Spring Bootアプリケーションをプログラムで再起動する方法をいくつか検討しました。

いつものように、例のソースコードはGitHubにあります。