Как я могу программно выключение 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);
}