Come posso programmazione arresto una primavera di avvio applicazione senza terminare la VM ?
In altri lavori, qual è il contrario di
new SpringApplication(Main.class).run(args);
Come posso programmazione arresto una primavera di avvio applicazione senza terminare la VM ?
In altri lavori, qual è il contrario di
new SpringApplication(Main.class).run(args);
Risposte:
Chiudere un SpringApplicationsignifica sostanzialmente chiudere il sottostante ApplicationContext. Il SpringApplication#run(String...)metodo ti dà che ApplicationContextcome file ConfigurableApplicationContext. Puoi quindi close()farlo da solo.
Per esempio,
@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();
}
}
In alternativa, puoi utilizzare il static SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)metodo helper per farlo per te. Per esempio,
@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);
}
}
ExitCodeGeneratorpuò essere utilizzato. Potresti semplicemente tornare dal mainmetodo per uscire con grazia (codice di uscita 0).
In un'applicazione di avvio primaverile puoi usare qualcosa di simile
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);
}
}
ApplicationContextpuò essere iniettato automaticamente in altri fagioli.
Funziona, anche se viene stampato.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Quindi aggiungendo .close()doporun()
Spiegazione:
public ConfigurableApplicationContext run(String... args)Esegui l'applicazione Spring, creando e aggiornando un nuovo ApplicationContext. parametri:
args- gli argomenti dell'applicazione (solitamente passati da un metodo principale Java)Restituisce: un ApplicationContext in esecuzione
e:
void close()Chiudere questo contesto dell'applicazione, rilasciando tutte le risorse e i blocchi che l'implementazione potrebbe contenere. Ciò include la distruzione di tutti i bean singleton memorizzati nella cache. Nota: non richiama close su un contesto genitore; i contesti genitore hanno il loro ciclo di vita indipendente.Questo metodo può essere chiamato più volte senza effetti collaterali: le successive chiamate di chiusura su un contesto già chiuso verranno ignorate.
Quindi, in pratica, non chiuderà il contesto genitore, ecco perché la VM non si chiude.
SpringApplication.exit(appContext, () -> returnCode).
SpringApplication.run(MyApplication.class, args), non esiste un contesto genitore. C'è solo un contesto, il contesto creato e restituito da run, che poi immediatamente close. @Michael ha ragione. Questo non funzionerà per i programmi che devono fare qualcosa dopo che il contesto Spring è stato inizializzato, che è la maggior parte dei programmi.
Nell'applicazione puoi usare SpringApplication. Questo ha un exit()metodo statico che accetta due argomenti: il ApplicationContexte un ExitCodeGenerator:
cioè puoi dichiarare questo metodo:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
All'interno dei test di integrazione puoi ottenerlo aggiungendo @DirtiesContextannotazioni a livello di classe:
@DirtiesContext(classMode=ClassMode.AFTER_CLASS) - L'ApplicationContext associato verrà contrassegnato come sporco dopo la classe di test.@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) - L'ApplicationContext associato verrà contrassegnato come sporco dopo ogni metodo di test nella classe.vale a dire
@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 {
...
Ciò assicurerà che l'applicazione SpringBoot sia chiusa correttamente e che le risorse vengano rilasciate di nuovo al sistema operativo,
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}