プログラムでSpring Bootアプリケーションをシャットダウンする


109

VMを終了せずにSpring Bootアプリケーションをプログラムでシャットダウンするにはどうすればよいですか?

他の作品では、その逆は何ですか

new SpringApplication(Main.class).run(args);

1
いい視点ね!その上でclose()を呼び出すと、うまくいきます。
Axel Fontaine


@AnandVarkeyPhilipsいいえ、そうではありません。これはAPIに関するもので、もう1つはopsがそうする方法に関するものです。
Axel Fontaine

わかりました。その質問リンクは他の人を助けるかもしれません。上記のコメントを削除しますか?
Anand Varkey Philips、

回答:


111

閉会SpringApplication根本を閉じて、基本的な手段をApplicationContextSpringApplication#run(String...)この方法は、あなたにその与えますApplicationContextようにConfigurableApplicationContext。その後、close()それを自分で行うことができます。

例えば、

@SpringBootApplication
public class Example {
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
        // ...determine it's time to shut down...
        ctx.close();
    }
}

または、static SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)ヘルパーメソッドを使用して行うこともできます。例えば、

@SpringBootApplication
public class Example {
    public static void main(String[] args) {
        ConfigurableApplicationContext ctx = SpringApplication.run(Example.class, args);
        // ...determine it's time to stop...
        int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
            @Override
            public int getExitCode() {
                // no errors
                return 0;
            }
        });

        // or shortened to
        // int exitCode = SpringApplication.exit(ctx, () -> 0);

        System.exit(exitCode);
    }
}

1
ctx.close();を使用する場合 最後にSystem.exit(n)を呼び出す必要はありませんか?コンテキストclose()にはSystem.exit()が必要ですか?
Denys

2
@拒否いいえ、コンテキストは閉じるときにJavaプロセスを終了しません。私の例の出口は、のExitCodeGenerator使用方法を示しています。mainメソッドから戻って正常に終了することもできます(終了コード0)。
Sotirios Delimanolis

78

春のブートアプリケーションでは、このようなものを使用できます

ShutdownManager.java

import org.springframework.context.ApplicationContext;
import org.springframework.boot.SpringApplication;

@Component
class ShutdownManager{

    @Autowired
    private ApplicationContext appContext;

    public void initiateShutdown(int returnCode){
        SpringApplication.exit(appContext, () -> returnCode);
    }
}

16
ApplicationContextが他のBeanに自動的に注入できることを示す賛成票です。
アンソニー・シュイナード

1
@snovelliシャットダウンの開始メソッドを呼び出す方法は?initializeShutdown(x)、x = 0?
StackOverFlow 2018

条件付きシャットダウンがある場合、これを実行できます。SpringApplication.run(..)。close()は、プログラムの完了時に行います。
アブバッカーシディック2018

なぜSpringApplication。(appContext、()-> returnCode); なぜappContext.close()ができないのですか?違いはなんですか ?
Rams

@StackOverFlow必要な場所にBeanを挿入し、正しくシャットダウンしている場合は、提案された戻りコード(x = 0)を渡す必要があります。たとえば、シャットダウンマネージャーをRestControllerに挿入してリモートシャットダウンを許可したり、ダウンストリームサービスがない場合にJVMをシャットダウンするヘルスチェックモニタリングに挿入したりできます
snovelli

36

これはうまくいき、できあがりも印刷されます。

  SpringApplication.run(MyApplication.class, args).close();
  System.out.println("done");

だから.close()後に追加run()

説明:

public ConfigurableApplicationContext run(String... args)

Springアプリケーションを実行し、新しいApplicationContextを作成して更新します。パラメーター:

args -アプリケーションの引数(通常はJavaメインメソッドから渡される)

戻り値: 実行中のApplicationContext

そして:

void close()このアプリケーションコンテキストを閉じ、実装が保持している可能性があるすべてのリソースとロックを解放します。これには、キャッシュされたすべてのシングルトンBeanの破棄が含まれます。注:親コンテキストでcloseを呼び出しません。親コンテキストには、独自の独立したライフサイクルがあります。

このメソッドは、副作用なしに複数回呼び出すことができます。すでに閉じられているコンテキストに対する後続のclose呼び出しは無視されます。

つまり、基本的には親コンテキストを閉じません。そのため、VMは終了しません。


2
このソリューションは、バッチのような短期間のプロセスで機能することを思い出してください。ただし、Spring MVCアプリケーションでは使用しないでください。起動後にアプリケーションがシャットダウンした。
Michael COLL

@MichaelCOLL問題は、タイプに関係なく、Spring Bootアプリをプログラムでシャットダウンする方法についてです。また、Spring MVC
ACVの

1
@ACVそのとおりです。うまく機能します。ただし、稼働し続ける必要があるアプリ(Spring MVCアプリなど)の場合、これは良い方法ではないと思います。私の場合、を使用しましたSpringApplication.exit(appContext, () -> returnCode)
Michael COLL

1
最後の行でどのVMを参照していますか?Spring BootアプリケーションをSpringApplication.run(MyApplication.class, args)で開始している場合、親コンテキストはありません。コンテキストは1つしかrunありませんclose。によって作成されて返されたコンテキストは、すぐにです。@Michaelは正しいです。これは、Springコンテキストが初期化された後に何かを行う必要があるプログラム(ほとんどのプログラム)では機能しません。
救い主

@Savior JVM。親コンテキストがあります。ここでは、Springブートアプリケーションをシャットダウンする方法について説明します。通常、この方法でWebアプリケーションをシャットダウンすることはありません。そのため、このメカニズムは通常、何かを実行して停止する必要がある短期間のアプリケーションに使用されます。デフォルトでは、バッチ処理が完了した後でもSpringブートは実行を継続するため、このメカニズムを使用します。
ACV

3

アプリケーションで使用できますSpringApplication。これは、静的に持つexit()2つの引数を取り方法ApplicationContext及びExitCodeGenerator

つまり、このメソッドを宣言できます。

@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
    SpringApplication.exit(applicationContext, exitCodeGenerator);
}

統合テストの内部では@DirtiesContext、クラスレベルで注釈を追加することでそれを実現できます。

  • @DirtiesContext(classMode=ClassMode.AFTER_CLASS) -関連するApplicationContextは、テストクラスの後でダーティとしてマークされます。
  • @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) -関連するApplicationContextは、クラスの各テストメソッドの後でダーティとしてマークされます。

すなわち

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {Application.class},
    webEnvironment= SpringBootTest.WebEnvironment.DEFINED_PORT, properties = {"server.port:0"})
@DirtiesContext(classMode= DirtiesContext.ClassMode.AFTER_CLASS)
public class ApplicationIT {
...

OK。ExecutorServiceExitCodeGeneratorはどこで取得する必要がありますか?Beanの場合、作成スニペットコード(および作成されたクラス)を表示できますか?どのクラスにメソッドshutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator)を置く必要がありますか?
Vlad G.

2

これにより、SpringBootアプリケーションが適切に閉じられ、リソースがオペレーティングシステムに解放されます。

@Autowired
private ApplicationContext context;

@GetMapping("/shutdown-app")
public void shutdownApp() {

    int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
    System.exit(exitCode);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.