VMを終了せずにSpring Bootアプリケーションをプログラムでシャットダウンするにはどうすればよいですか?
他の作品では、その逆は何ですか
new SpringApplication(Main.class).run(args);
VMを終了せずにSpring Bootアプリケーションをプログラムでシャットダウンするにはどうすればよいですか?
他の作品では、その逆は何ですか
new SpringApplication(Main.class).run(args);
回答:
閉会SpringApplication
根本を閉じて、基本的な手段をApplicationContext
。SpringApplication#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);
}
}
ExitCodeGenerator
使用方法を示しています。main
メソッドから戻って正常に終了することもできます(終了コード0)。
春のブートアプリケーションでは、このようなものを使用できます
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);
}
}
ApplicationContext
が他のBeanに自動的に注入できることを示す賛成票です。
これはうまくいき、できあがりも印刷されます。
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は終了しません。
SpringApplication.exit(appContext, () -> returnCode)
。
SpringApplication.run(MyApplication.class, args)
で開始している場合、親コンテキストはありません。コンテキストは1つしかrun
ありませんclose
。によって作成されて返されたコンテキストは、すぐにです。@Michaelは正しいです。これは、Springコンテキストが初期化された後に何かを行う必要があるプログラム(ほとんどのプログラム)では機能しません。
アプリケーションで使用できます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 {
...
これにより、SpringBootアプリケーションが適切に閉じられ、リソースがオペレーティングシステムに解放されます。
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}