Bir Spring Boot uygulamasını VM'yi sonlandırmadan programlı olarak nasıl kapatabilirim ?
Diğer çalışmalarda, tam tersi ne
new SpringApplication(Main.class).run(args);
Bir Spring Boot uygulamasını VM'yi sonlandırmadan programlı olarak nasıl kapatabilirim ?
Diğer çalışmalarda, tam tersi ne
new SpringApplication(Main.class).run(args);
Yanıtlar:
Birini kapatmak, SpringApplication
temelde temelini kapatmak anlamına gelir ApplicationContext
. SpringApplication#run(String...)
Yöntem size bunu sağlıyor ApplicationContext
bir şekilde ConfigurableApplicationContext
. O close()
zaman kendiniz yapabilirsiniz .
Örneğin,
@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();
}
}
Alternatif olarak, bunu sizin yerinize static
SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)
yapmak için yardımcı yöntemi kullanabilirsiniz. Örneğin,
@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
kullanılabileceğini gösteriyor. main
Nazikçe çıkmak için yöntemden dönebilirsiniz (çıkış kodu 0).
İlkbahar önyükleme uygulamasında bunun gibi bir şey kullanabilirsiniz
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
Otomatik olarak diğer çekirdeklere enjekte edilebileceğini göstermek için oy verin .
Bu işler, hatta yapılır basılmıştır.
SpringApplication.run(MyApplication.class, args).close();
System.out.println("done");
Yani .close()
sonra eklemekrun()
Açıklama:
public ConfigurableApplicationContext run(String... args)
Spring uygulamasını çalıştırın, yeni bir ApplicationContext oluşturun ve yenileyin. Parametreler:
args
- uygulama argümanları (genellikle bir Java ana yönteminden geçirilir)Döndürür: çalışan bir ApplicationContext
ve:
void close()
Uygulamanın tutabileceği tüm kaynakları ve kilitleri serbest bırakarak bu uygulama bağlamını kapatın. Bu, önbelleğe alınmış tüm tekil çekirdeklerinin yok edilmesini içerir. Not: Bir üst bağlamda close çağırmaz; üst bağlamların kendi bağımsız yaşam döngüleri vardır.Bu yöntem, yan etkiler olmaksızın birden çok kez çağrılabilir: Zaten kapalı bir bağlamda sonraki yakın çağrılar dikkate alınmaz.
Yani temelde, ana bağlamı kapatmayacak, bu yüzden VM kapanmıyor.
SpringApplication.exit(appContext, () -> returnCode)
.
SpringApplication.run(MyApplication.class, args)
, üst bağlam yoktur. Sadece bir bağlam vardır, bağlam yaratılır ve geri döner run
, o zaman bunu hemen yaparsınız close
. @Michael haklı. Bu, çoğu program olan Bahar bağlamı başlatıldıktan sonra herhangi bir şey yapması gereken programlar için çalışmayacaktır.
Uygulamada kullanabilirsiniz SpringApplication
. Bu, exit()
iki bağımsız değişken alan statik bir yönteme sahiptir: ApplicationContext
ve bir ExitCodeGenerator
:
yani bu yöntemi beyan edebilirsiniz:
@Autowired
public void shutDown(ExecutorServiceExitCodeGenerator exitCodeGenerator) {
SpringApplication.exit(applicationContext, exitCodeGenerator);
}
Entegrasyon testlerinin içine@DirtiesContext
, sınıf düzeyinde not ekleyerek bunu başarabilirsiniz :
@DirtiesContext(classMode=ClassMode.AFTER_CLASS)
- İlişkili ApplicationContext, test sınıfından sonra kirli olarak işaretlenecektir.@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
- İlişkili ApplicationContext, sınıftaki her test yönteminden sonra kirli olarak işaretlenecektir.yani
@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 {
...
Bu, SpringBoot uygulamasının düzgün bir şekilde kapatılmasını ve kaynakların işletim sistemine geri verilmesini sağlayacaktır.
@Autowired
private ApplicationContext context;
@GetMapping("/shutdown-app")
public void shutdownApp() {
int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
System.exit(exitCode);
}