Jak mogę programowo wyłączenie Wiosna Boot aplikacja bez kończące VM ?
W innych pracach, co jest przeciwieństwem
new SpringApplication(Main.class).run(args);
Jak mogę programowo wyłączenie Wiosna Boot aplikacja bez kończące VM ?
W innych pracach, co jest przeciwieństwem
new SpringApplication(Main.class).run(args);
Odpowiedzi:
Zamknięcie SpringApplication
zasadniczo oznacza zamknięcie instrumentu bazowego ApplicationContext
. SpringApplication#run(String...)
Metoda daje to ApplicationContext
jako ConfigurableApplicationContext
. Możesz close()
to samemu.
Na przykład,
@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();
}
}
Alternatywnie możesz użyć static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
metody pomocnika, aby zrobić to za siebie. Na przykład,
@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
można użyć. Możesz po prostu powrócić z main
metody, aby bezpiecznie zakończyć (kod zakończenia 0).
W aplikacji do rozruchu wiosennego możesz użyć czegoś takiego
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
może być automatycznie wstrzykiwany do innych ziaren.
To działa, nawet gotowe jest drukowane.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Więc dodając .close()
porun()
Wyjaśnienie:
public ConfigurableApplicationContext run(String... args)
Uruchom aplikację Spring, tworząc i odświeżając nowy ApplicationContext. Parametry:
args
- argumenty aplikacji (zwykle przekazywane z głównej metody Java)Zwraca: działający ApplicationContext
i:
void close()
Zamknij ten kontekst aplikacji, zwalniając wszystkie zasoby i blokady, które może zawierać implementacja. Obejmuje to niszczenie wszystkich pojedynczych ziaren w pamięci podręcznej. Uwaga: nie wywołuje zamknięcia w kontekście nadrzędnym; konteksty nadrzędne mają swój własny, niezależny cykl życia.Tę metodę można wywołać wiele razy bez skutków ubocznych: kolejne bliskie wywołania w już zamkniętym kontekście będą ignorowane.
Zasadniczo więc nie zamknie kontekstu nadrzędnego, dlatego maszyna wirtualna się nie kończy.
SpringApplication.exit(appContext, () -> returnCode)
.
SpringApplication.run(MyApplication.class, args)
, nie ma kontekstu nadrzędnego. Jest tylko jeden kontekst, kontekst utworzony i zwrócony przez run
, który następnie natychmiast close
. @Michael ma rację. To nie zadziała w przypadku programów, które muszą cokolwiek robić po zainicjowaniu kontekstu Spring, czyli w przypadku większości programów.
W aplikacji możesz użyć SpringApplication
. Ma exit()
metodę statyczną , która przyjmuje dwa argumenty: the ApplicationContext
i an ExitCodeGenerator
:
czyli możesz zadeklarować tę metodę:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
Wewnątrz testów integracyjnych możesz to osiągnąć, dodając @DirtiesContext
adnotację na poziomie klasy:
@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
- Powiązany ApplicationContext zostanie oznaczony jako brudny po klasie testowej.@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
- Powiązany ApplicationContext zostanie oznaczony jako brudny po każdej metodzie testowej w klasie.to znaczy
@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 {
...
Dzięki temu aplikacja SpringBoot zostanie poprawnie zamknięta, a zasoby zostaną zwrócone do systemu operacyjnego,
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}