如何在不终止VM的情况下以编程方式关闭Spring Boot应用程序?
在其他作品中,
new SpringApplication(Main.class).run(args);
如何在不终止VM的情况下以编程方式关闭Spring Boot应用程序?
在其他作品中,
new SpringApplication(Main.class).run(args);
Answers:
关闭a 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)。
在Spring Boot应用程序中,您可以使用类似以下的内容
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 main方法传递)返回: 运行中的ApplicationContext
和:
void close()
关闭此应用程序上下文,释放实现可能持有的所有资源和锁。这包括销毁所有缓存的单例bean。注意:不会在父上下文上调用关闭;父级上下文具有自己的独立生命周期。可以多次调用此方法,而不会产生副作用:在已经关闭的上下文上进行的后续关闭调用将被忽略。
因此,基本上,它不会关闭父上下文,这就是VM不退出的原因。
SpringApplication.exit(appContext, () -> returnCode)
。
SpringApplication.run(MyApplication.class, args)
,则没有父上下文。仅有一个上下文,该上下文是由创建和返回的run
,然后您可以立即进行创建close
。@迈克尔是正确的。这对于大多数在Spring初始化后需要执行任何操作的程序不起作用。
在应用程序中,您可以使用SpringApplication
。它有一个带有exit()
两个参数的静态方法:the ApplicationContext
和an 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);
}