Comment puis-je arrêter par programme a Spring Boot application sans mettre fin à la machine virtuelle?
Dans d’autres œuvres, quel est le contraire de
new SpringApplication(Main.class).run(args);
Fermer un SpringApplication
signifie fondamentalement fermer le ApplicationContext
sous-jacent. La méthode SpringApplication#run(String...)
vous donne ce ApplicationContext
sous la forme d'un ConfigurableApplicationContext
. Vous pouvez alors close()
vous-même. Par exemple,
@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();
}
}
Sinon, vous pouvez utiliser la méthode d'assistance static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
== pour le faire à votre place. Par exemple,
@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;
}
});
System.exit(exitCode);
}
}
Dans une application de démarrage de printemps, vous pouvez utiliser quelque chose comme ça
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);
}
}
Cela fonctionne, même fait est imprimé.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Donc, en ajoutant .close()
après run()
Explication:
public ConfigurableApplicationContext run(String... args)
Exécutez l'application Spring pour créer et actualiser un nouveau contexte d'application. Paramètres:
args
- les arguments de l'application (généralement passés d'une Java)Retourne: n ApplicationContext en cours d'exécution
et:
void close()
Ferme ce contexte d'application en libérant toutes les ressources et tous les verrous que l'implémentation peut contenir. Cela inclut la destruction de tous les beans singleton en cache. Remarque: N'appelle pas la fermeture sur un contexte parent. les contextes parents ont leur propre cycle de vie indépendant.Cette méthode peut être appelée plusieurs fois sans effets secondaires: Les appels ultérieurs ultérieurs dans un contexte déjà fermé seront ignorés.
Donc, fondamentalement, le contexte parent ne sera pas fermé, c’est pourquoi le VM ne s’arrête pas.
Dans l'application vous pouvez utiliser SpringApplication
. Cela a une méthode statique exit()
qui prend deux arguments: le ApplicationContext
et un ExitCodeGenerator
:
c'est-à-dire que vous pouvez déclarer cette méthode:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
À l’intérieur des tests d’intégration vous pouvez y parvenir en ajoutant une annotation @DirtiesContext
Au niveau de la classe:
@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
- Le contexte d'application associé sera marqué comme sale après la classe de test.@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
- Le contexte d'application associé sera marqué comme sale après chaque méthode de test de la classe.c'est à 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 {
...
Cela garantira que l'application Spring Boot est correctement fermée et que les ressources sont libérées sur le système d'exploitation.
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}