Wie kann ich eine Spring Boot- Anwendung programmgesteuert herunterfahren, ohne die VM zu beenden ?
In anderen Werken, was ist das Gegenteil von
new SpringApplication(Main.class).run(args);
Wie kann ich eine Spring Boot- Anwendung programmgesteuert herunterfahren, ohne die VM zu beenden ?
In anderen Werken, was ist das Gegenteil von
new SpringApplication(Main.class).run(args);
Antworten:
Das Schließen von a SpringApplication
bedeutet im Grunde das Schließen des Basiswerts ApplicationContext
. Die SpringApplication#run(String...)
Methode gibt Ihnen das ApplicationContext
als ConfigurableApplicationContext
. Sie können es dann close()
selbst tun.
Beispielsweise,
@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();
}
}
Alternativ können Sie die static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
Hilfsmethode verwenden, um dies für Sie zu tun. Beispielsweise,
@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
verwendet werden kann. Sie können einfach von der main
Methode zurückkehren, um ordnungsgemäß zu beenden (Beendigungscode 0).
In einer Spring Boot-Anwendung können Sie so etwas verwenden
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
automatisch in andere Bohnen injiziert werden kann.
Dies funktioniert, auch wenn es gedruckt wird.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Also .close()
nachher hinzufügenrun()
Erläuterung:
public ConfigurableApplicationContext run(String... args)
Führen Sie die Spring-Anwendung aus und erstellen und aktualisieren Sie einen neuen ApplicationContext. Parameter:
args
- die Anwendungsargumente (normalerweise von einer Java-Hauptmethode übergeben)Rückgabe: ein laufender ApplicationContext
und:
void close()
Schließen Sie diesen Anwendungskontext und geben Sie alle Ressourcen und Sperren frei, die die Implementierung möglicherweise enthält. Dies beinhaltet das Zerstören aller zwischengespeicherten Singleton-Beans. Hinweis: Ruft in einem übergeordneten Kontext nicht close auf. Elternkontexte haben ihren eigenen, unabhängigen Lebenszyklus.Diese Methode kann ohne Nebenwirkungen mehrmals aufgerufen werden: Nachfolgende Abschlussaufrufe in einem bereits geschlossenen Kontext werden ignoriert.
Im Grunde genommen wird der übergeordnete Kontext nicht geschlossen. Deshalb wird die VM nicht beendet.
SpringApplication.exit(appContext, () -> returnCode)
.
SpringApplication.run(MyApplication.class, args)
, gibt es keinen übergeordneten Kontext. Es gibt nur einen Kontext, den Kontext run
, der von Ihnen erstellt und zurückgegeben wird , den Sie dann sofort close
. @ Michael ist richtig. Dies funktioniert nicht für Programme, die nach der Initialisierung des Spring-Kontexts etwas tun müssen. Dies sind die meisten Programme.
In der Anwendung können Sie verwenden SpringApplication
. Dies hat eine statische exit()
Methode, die zwei Argumente akzeptiert: das ApplicationContext
und ein ExitCodeGenerator
:
dh Sie können diese Methode deklarieren:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
Innerhalb der Integrationstests können Sie dies erreichen, indem Sie @DirtiesContext
Anmerkungen auf Klassenebene hinzufügen :
@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
- Der zugehörige ApplicationContext wird nach der Testklasse als fehlerhaft markiert.@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
- Der zugehörige ApplicationContext wird nach jeder Testmethode in der Klasse als fehlerhaft markiert.dh
@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 {
...
Dadurch wird sichergestellt, dass die SpringBoot-Anwendung ordnungsgemäß geschlossen und die Ressourcen wieder für das Betriebssystem freigegeben werden.
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}