Cierre programáticamente de la aplicación Spring Boot

¿Cómo puedo cerrar programáticamente una aplicación Spring Boot sin finalizar la VM ?

En otros trabajos, ¿qué es lo opuesto a

new SpringApplication(Main.class).run(args); 

Cerrar una aplicación SpringApplication básicamente significa cerrar el ApplicationContext subyacente. El SpringApplication#run(String...) le proporciona ese ApplicationContext como un ConfigurableApplicationContext . Entonces puede close() usted mismo. Por ejemplo,

 @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(); } } 

Alternativamente, puede usar el método de ayuda static SpringApplication.exit(ApplicationContext, ExitCodeGenerator...) para hacerlo por usted. Por ejemplo,

 @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); } } 

En una aplicación de arranque de spring puedes usar algo como esto

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); } } 

Esto funciona, incluso hecho está impreso.

  SpringApplication.run(MyApplication.class, args).close(); System.out.println("done"); 

Entonces agregando .close() después de run()

Explicación:

public ConfigurableApplicationContext run(String... args)

Ejecute la aplicación Spring, creando y actualizando un nuevo ApplicationContext. Parámetros:

args : los argumentos de la aplicación (generalmente pasados ​​desde un método principal de Java)

Devuelve: un ApplicationContext en ejecución

y:

void close() Cierre el contexto de esta aplicación, liberando todos los recursos y lockings que pueda contener la implementación. Esto incluye destruir todos los beans singleton almacenados en caché. Nota: no invoca cerca de un contexto principal; los contextos de los padres tienen su propio ciclo de vida independiente.

Este método se puede llamar varias veces sin efectos secundarios: se ignorarán las próximas llamadas en un contexto ya cerrado.

Así que, básicamente, no cerrará el contexto principal, es por eso que la máquina virtual no se cierra.

En la aplicación puedes usar SpringApplication . Tiene un método static exit() que toma dos argumentos: ApplicationContext y ExitCodeGenerator :

es decir, puede declarar este método:

 @Autowired public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) { SpringApplication.exit(applicationContext, exitCodeGenerator); } 

Dentro de las pruebas de integración puede lograrlo agregando la anotación @DirtiesContext a nivel de clase:

  • @DirtiesContext(classMode=ClassMode.AFTER_CLASS) – El ApplicationContext asociado se marcará como sucio después de la clase de prueba.
  • @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) – El ApplicationContext asociado se marcará como sucio después de cada método de prueba en la clase.

es decir

 @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 { ...