以编程方式关闭 SpringBoot 应用程序

我如何能 程序关闭一个 弹簧靴应用程序 而不终止虚拟机

在其他作品中,什么是

new SpringApplication(Main.class).run(args);
140388 次浏览

关闭 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);
}
}

这工程,即使做了是印刷。

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

因此在 run()之后加入 .close()

说明:

public ConfigurableApplicationContext run(String... args)

运行 Spring 应用程序,创建并刷新一个新的 应用程序上下文参数:

args-应用程序参数(通常从 Java 主 方法)

返回: 正在运行的 ApplicationContext

以及:

关闭此应用程序上下文,释放所有资源 以及实现可能持有的锁。这包括销毁 所有缓存的单例 bean。注意: 不在父级上调用 close 父上下文有自己独立的生命周期。

这种方法可以多次调用,没有副作用: 对已关闭上下文的后续闭合调用将被忽略。

所以基本上,它不会关闭父上下文,这就是 VM 不退出的原因。

最简单的方法是在需要启动关闭的地方注入以下对象

ShutdownManager.java

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


@Component
class ShutdownManager {


@Autowired
private ApplicationContext appContext;


/*
* Invoke with `0` to indicate no error or different code to indicate
* abnormal exit. es: shutdownManager.initiateShutdown(0);
**/
public void initiateShutdown(int returnCode){
SpringApplication.exit(appContext, () -> returnCode);
}
}

在应用程序 中可以使用 SpringApplication。这有一个静态的 exit()方法,它接受两个参数: ApplicationContextExitCodeGenerator:

也就是说,你可以声明这个方法:

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

在 Integration test 中,可以通过在类级别添加 @DirtiesContext注释来实现:

  • @DirtiesContext(classMode=ClassMode.AFTER_CLASS)-在测试类之后,相关的 ApplicationContext 将被标记为 Dirty。
  • @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)-在类中的每个测试方法之后,相关的 ApplicationContext 将被标记为 Dirty。

也就是说。

@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);
}