1概要

このチュートリアルでは、Spring Bootアプリケーションをプログラム的に再起動する方法を説明します。

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

  • いくつかのパラメータを変更した際の設定ファイルの再読み込み

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

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

この記事ではSpring Bootアプリケーションを再起動する機能について説明していますが、https://www.baeldung.com/spring-boot-shutdown[Spring Bootアプリケーションのシャットダウン]に関する素晴らしいチュートリアルもあります。

それでは、Spring Bootアプリケーションの再起動を実装するためのさまざまな方法を検討しましょう。


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つの方法は、

httpsから組み込みの

RestartEndpoint__を使用することです。

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

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-cloud-starter</artifactId>
</dependency>

次に、

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アプリケーションコンテキストの更新

場合によっては、https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/ConfigurableApplicationContext.html#refresh–[refreshを呼び出して、アプリケーションコンテキストをリロードできます。]方法。

この方法は有望に思えるかもしれませんが、すでに初期化されたコンテキストのリフレッシュをサポートするのは一部のアプリケーションコンテキストタイプのみです。たとえば、

FileSystemXmlApplicationContext



GroovyWebApplicationContext、

などのいくつかがサポートしています。

残念ながら、Spring Boot Webアプリケーションでこれを試すと、次のエラーが発生します。

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

最後に、複数の更新をサポートするコンテキストタイプがいくつかありますが、これを避けるべきです。その理由は、

refresh

メソッドは、アプリケーションコンテキストを初期化するためにフレームワークによって使用される内部メソッドとして設計されているためです。


5結論

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

いつものように、例のソースコードはhttps://github.com/eugenp/tutorials/tree/master/spring-boot-ops[GitHub]にあります。