프로그래밍 방식으로 Spring Boot 애플리케이션 종료


109

내가 어떻게 프로그램 종료 봄 부팅 응용 프로그램 VM을 종료하지 않고 ?

다른 작품에서 반대되는 것은 무엇입니까?

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

1
좋은 지적! close ()를 호출하면 작업이 수행됩니다.
Axel Fontaine 2014


@AnandVarkeyPhilips 아니요, 그렇지 않습니다. 이것은 API에 관한 것이고 다른 하나는 오퍼레이션이 그렇게하는 방법에 관한 것입니다.
Axel Fontaine

좋아요 .. 그 질문 링크는 다른 사람들에게 도움이 될 수 있습니다. 위의 댓글을 삭제 하시겠습니까?
Anand Varkey Philips

답변:


111

닫기는 SpringApplication기본적으로 기본 ApplicationContext. SpringApplication#run(String...)방법은 당신이주는 ApplicationContextA와를 ConfigurableApplicationContext. 그런 다음 close()직접 할 수 있습니다 .

예를 들면

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

또는 static SpringApplication.exit(ApplicationContext, ExitCodeGenerator...)도우미 메서드를 사용하여 수행 할 수 있습니다. 예를 들면

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

1
ctx.close (); 사용하면 마지막에 System.exit (n)을 호출 할 필요가 없습니까? 컨텍스트 close () 안에 System.exit ()가 있어야합니까?
Denys 2011

2
@Denys 아니요, 컨텍스트는 닫을 때 Java 프로세스를 종료하지 않습니다. 내 예제의 이탈 ExitCodeGenerator은이 사용 방법을 보여줍니다 . main메서드 에서 돌아와서 정상적으로 종료 할 수 있습니다 (종료 코드 0).
Sotirios Delimanolis 2019

78

스프링 부트 애플리케이션에서 다음과 같이 사용할 수 있습니다.

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

16
ApplicationContext을 다른 빈에 자동으로 주입 할 수 있음 을 보여주기 위해 찬성합니다 .
안토니 Chuinard

1
@snovelli 종료 방법을 시작하는 방법은 무엇입니까? initializeShutdown (x), x = 0?
StackOverFlow

조건부 종료가 있으면 실행할 수 있습니다. 프로그램이 완료되면 SpringApplication.run (..). close ()가 수행됩니다.
Abubacker Siddik 2018

왜 SpringApplication. (appContext, ()-> returnCode); 왜 appContext.close ()를 할 수 없습니까? 차이점은 무엇입니까?
Rams

@StackOverFlow 필요한 곳에 빈을 주입 한 다음 올바르게 종료되는 경우 제안한대로 (x = 0) 반환 코드를 전달해야합니다. 예를 들어 Shutdown Manager를 RestController에 삽입하고 원격 종료를 허용하거나 다운 스트림 서비스가 누락 된 경우 JVM을 종료하는 상태 검사 모니터링에 삽입 할 수 있습니다.
snovelli

36

이것은 작동합니다.

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

추가 그래서 .close()run()

설명:

public ConfigurableApplicationContext run(String... args)

Spring 애플리케이션을 실행하여 새 ApplicationContext를 만들고 새로 고칩니다. 매개 변수 :

args -응용 프로그램 인수 (일반적으로 Java 기본 메서드에서 전달됨)

반환 값 : 실행중인 ApplicationContext

과:

void close()이 애플리케이션 컨텍스트를 닫고 구현이 보유 할 수있는 모든 자원 및 잠금을 해제하십시오. 여기에는 캐시 된 모든 싱글 톤 Bean 삭제가 포함됩니다. 참고 : 상위 컨텍스트에서 닫기를 호출하지 않습니다. 상위 컨텍스트에는 고유 한 독립적 인 수명주기가 있습니다.

이 메서드는 부작용없이 여러 번 호출 될 수 있습니다. 이미 닫힌 컨텍스트에 대한 후속 닫기 호출은 무시됩니다.

따라서 기본적으로 부모 컨텍스트를 닫지 않으므로 VM이 종료되지 않습니다.


2
이 솔루션은 배치와 같은 단기 프로세스에서 작동하지만 Spring MVC 애플리케이션에서는 사용하지 마십시오. 응용 프로그램이 부팅 후 종료됩니다.
Michael COLL

@MichaelCOLL 질문은 유형에 관계없이 프로그래밍 방식으로 스프링 부트 앱을 종료하는 방법에 관한 것입니다. Spring MVC에서도 작동합니다
ACV

1
@ACV 당신 말이 맞아요, 아주 잘 작동합니다. 그러나 (Spring MVC 앱과 같이) 계속 유지되어야하는 앱의 경우에는 이것이 좋은 방법이 아니라고 생각합니다. 제 경우에는 SpringApplication.exit(appContext, () -> returnCode).
Michael COLL

1
마지막 줄에서 어떤 VM을 언급하고 있습니까? 를 사용하여 Spring Boot 애플리케이션을 시작하는 경우 SpringApplication.run(MyApplication.class, args)부모 컨텍스트가 없습니다. 하나의 컨텍스트 생성에 의해 반환 된 컨텍스트있어 run다음 바로는 close. @Michael이 맞습니다. 이것은 대부분의 프로그램 인 Spring 컨텍스트가 초기화 된 후에 아무것도해야하는 프로그램에서는 작동하지 않습니다.
구세주

@Savior JVM. 부모 컨텍스트가 있습니다. 여기서는 Spring 부트 애플리케이션을 종료하는 방법에 대해 설명합니다. 일반적으로 이런 방식으로 웹 애플리케이션을 종료하지 않습니다. 따라서이 메커니즘은 일반적으로 중지해야하는 작업을 수행하는 단기 응용 프로그램에 사용됩니다. 기본적으로 Spring boot는 일괄 처리를 마친 후에도 계속 실행되므로이 ​​메커니즘을 사용하고 싶을 것입니다.
ACV

3

응용 프로그램에서 당신은 사용할 수 있습니다 SpringApplication. 여기에는 exit()두 개의 인수를 받는 정적 메서드가 있습니다 : the ApplicationContext및 an ExitCodeGenerator:

즉,이 메서드를 선언 할 수 있습니다.

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

통합 테스트 내@DirtiesContext 에서 클래스 수준에서 주석을 추가하여이를 달성 할 수 있습니다 .

  • @DirtiesContext(classMode=ClassMode.AFTER_CLASS) -연결된 ApplicationContext는 테스트 클래스 이후에 더티로 표시됩니다.
  • @DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD) -연결된 ApplicationContext는 클래스의 각 테스트 메서드 후에 더티로 표시됩니다.

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

확인. ExecutorServiceExitCodeGenerator를 어디서 구해야합니까? Bean 인 경우 생성 스 니펫 코드 (및 생성 된 클래스)를 표시 할 수 있습니까? 어떤 클래스에 shutDown (ExecutorServiceExitCodeGenerator exitCodeGenerator) 메서드를 넣어야합니까?
Vlad G.

2

이렇게하면 SpringBoot 애플리케이션이 제대로 닫히고 리소스가 운영 체제로 다시 해제됩니다.

@Autowired
private ApplicationContext context;

@GetMapping("/shutdown-app")
public void shutdownApp() {

    int exitCode = SpringApplication.exit(context, (ExitCodeGenerator) () -> 0);
    System.exit(exitCode);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.