Как программно завершить работу приложения Spring Boot без прерывания работы виртуальной машины?
В других работах, что является противоположностью
new SpringApplication(Main.class).run(args);
Как программно завершить работу приложения 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 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 time to stop...
int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
// no errors
return 0;
}
});
System.exit(exitCode);
}
}
В приложении весенней загрузки вы можете использовать что-то вроде этого
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);
}
}
Это работает, даже сделано напечатано.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Так что добавление .close()
после run()
Объяснение:
public ConfigurableApplicationContext run(String... args)
Запустите приложение Spring, создав и обновив новый ApplicationContext. Параметры:
args
- аргументы приложения (обычно передаются из основного метода Java)Возвращает: работающий ApplicationContext
а также:
void close()
Закройте этот контекст приложения, освободив все ресурсы и блокировки, которые может содержать реализация. Это включает в себя уничтожение всех кэшированных синглтон-бинов. Примечание: не вызывает close в родительском контексте; родительские контексты имеют свой собственный, независимый жизненный цикл.Этот метод может вызываться несколько раз без побочных эффектов: последующие закрытые вызовы в уже закрытом контексте будут игнорироваться.
Таким образом, в основном, он не закроет родительский контекст, поэтому виртуальная машина не закрывается.
В приложении вы можете использовать SpringApplication
. У этого есть статический метод exit()
, который принимает два аргумента: 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);
}