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 SpringApplication
significa sostanzialmente chiudere il sottostante ApplicationContext
. Il SpringApplication#run(String...)
metodo ti dà che ApplicationContext
come 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);
}
}
ExitCodeGenerator
può essere utilizzato. Potresti semplicemente tornare dal main
metodo 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);
}
}
ApplicationContext
può 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 ApplicationContext
e 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 @DirtiesContext
annotazioni 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);
}