Як я можу програмно вимикання 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
можна автоматично вводити іншу квасолю.
Це працює, навіть зроблено, друкується.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Так додавання .close()
післяrun()
Пояснення:
public ConfigurableApplicationContext run(String... args)
Запустіть програму Spring, створивши та оновивши новий ApplicationContext. Параметри:
args
- аргументи програми (зазвичай передаються з основного методу Java)Повертає: запущений ApplicationContext
і:
void close()
Закрийте цей контекст програми, вивільнивши всі ресурси та блокування, які може містити реалізація. Сюди входить знищення всіх кешованих бобів однотонних. Примітка: не викликає закриття в батьківському контексті; батьківські контексти мають свій, незалежний життєвий цикл.Цей метод можна викликати кілька разів без побічних ефектів: Наступні закриті дзвінки у вже закритому контексті будуть ігноровані.
Отже, це не закриє батьківський контекст, тому VM не виходить.
SpringApplication.exit(appContext, () -> returnCode)
.
SpringApplication.run(MyApplication.class, args)
, батьківський контекст не існує. Є лише один контекст, створений і повернутий контекст run
, який ви негайно close
. @Michael має рацію. Це не спрацює для програм, яким потрібно нічого робити після ініціалізації весняного контексту, що є більшості програм.
У додатку ви можете використовувати 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);
}