Как я могу программно выключение Spring загрузки приложений , не выключая виртуальную машину ?
В других произведениях то, что противоположно
new SpringApplication(Main.class).run(args);
Как я могу программно выключение Spring загрузки приложений , не выключая виртуальную машину ?
В других произведениях то, что противоположно
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можно автоматически вводить в другие beans.
Это работает, даже сделано напечатано.
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-компонентов. Примечание. Не вызывает закрытие родительского контекста; родительские контексты имеют свой собственный независимый жизненный цикл.Этот метод можно вызывать несколько раз без побочных эффектов: последующие вызовы закрытия в уже закрытом контексте будут игнорироваться.
По сути, он не закрывает родительский контекст, поэтому виртуальная машина не закрывается.
SpringApplication.exit(appContext, () -> returnCode).
SpringApplication.run(MyApplication.class, args), родительский контекст отсутствует. Есть только один контекст, контекст, созданный и возвращенный run, который вы затем немедленно close. @ Майкл прав. Это не сработает для программ, которым нужно что-либо делать после инициализации контекста Spring, а это большинство программ.
В приложении можно использовать 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);
}