spring / / 2023. 11. 19. 20:20

스프링부트 Application Starting Events

스프링에는 다양한 종류의 이벤트들이 있어서 개발자들이 애플리케이션과 컨텍스트의 생명주기의 특정 지점에서 특정 작업을 수행할 수 있도록 해준다.

애플리케이션에서 수동으로 이 이벤트들을 사용하는 일은 드물기는 하지만 프레임워크 내에서는 매우 강력하게 사용을 하고 있다.

1. 다양한 이벤트들

ApplicationStartingEvent

ApplicationStartingEvent는 리스너 등록을 제외하고 특정 처리 전에 실행하는 시점에 발생한다.

ApplicationEnvironmentPreparedEvent

ApplicationEnvironmentPreparedEvent는 컨텍스트에서 Environment가 사용 가능할 때 발생한다.

Environment가 이 시점에서 준비되기 때문에 다른 빈이 사용하기 전에 수정할 수 있다.

ApplicationContextInitializedEvent

ApplicationContext가 준비되고 ApplicationContextInitializers가 호출되었지만 빈(Bean)은 아직 로드되지 않았을 때 ApplicationContextInitializedEvent가 호출된다.

빈(bean)이 스프링 컨테이너에 초기화되기 전에 특정 작업을 수행하기 위해 사용될 수 있다.

ApplicationPreparedEvent

ApplicationPreparedEventApllicationContext가 준비되었지만 아직 갱신되지 않았을 때 발생한다.

Environment가 사용 가능하고 빈(bean)이 로딩되었다.

ContextRefreshedEvent

ContextRefreshedEventApplicationContext가 초기화하거나 갱신되었을 때 발생한다. 일반적으로 갱신(refresh)는 컨텍스트가 종료되지 않는 한 여러번 발생할 수 있다.

ContextRefreshedEvent는 스프링 부트가 아닌 스프링에 존재하는 것이고 SpringApplicationEvent를 확장하지는 않는다.

ContextStartedEvent

ConfigurableApplicationContext에서 start() 메소드를 호출함으로서 이 이벤트를 발생하고 ApplicationContext를 시작할 수 있다. 사실 중지 후에 빈을 재시작하기 위해 사용된다. 자동 시작을 위한 특정 구성없이 컴포넌트를 처리하기 위해 메소드를 사용할 수 있다.

여기서, refresh()와는 대조적으로 start()를 호출하는 것은 명시적이다는 것을 명심하자.

WebServerInitializedEvent

웹서버를 사용하고 있다면 웹서버가 준비상태가 되면 WebServerInitializedEvent가 발생한다. ServletWebServerInitializedEventReactiveWebServerInitializedEvent는 각각 서블릿과 reactive를 나타낸다.

WebServerInitializedEventSpringApplicationEvent를 확장하지는 않는다.

ApplicationStartedEvent

ApplicationStartedEvent는 컨텍스트가 갱신되었지만 애플리케이션이 command-line runner가 호출되기 전에 발생한다.

ApplicationReadyEvent

ApplicationReadyEvent는 서비스 요청이 준비되었을 때 발생한다.

모든 초기화 단계가 완료되었기 때문에 이 시점에 내부 상태를 수정해서는 안된다.

ApplicationFailedEvent

ApplicationFailedEvent는 예외가 발생하여 애플리케이션이 시작하는 데 실패하였을 때 발생한다. 시작 단계 동안 어떤 경우에도 발생할 수 있다.

시작 실패 시 스크립트를 실행하는 특정 작성을 수행할 수 있다.

ContextStoppedEvent

ContextStoppedEventConfigurableApplicationContext의 stop 메소드를 호출할 때 AplicationContext가 중지되었을 때 발행된다.

ContextClosedEvent

이 이벤트는 ConfigurableApplicationContext에서 close() 메소드를 사용하여 ApplicationContext가 닫혔을 때 발생한다. 실제로는 컨텍스트가 닫힌 후에 재시작할 수 없다.

2. 실제 동작

위에서 정의한 이벤트가 어떻게 발생하는 지 코드로 작성해보자.

아래와 같이 @EventListener를 통해 코드를 작성해보자.

@Slf4j
@Component
public class EventHandlers {

    @EventListener(ContextRefreshedEvent.class)
    public void onContextRefreshedEvent(ContextRefreshedEvent event) {
        log.info("# ContextRefreshedEvent");
    }

    @EventListener(ContextStartedEvent.class)
    public void onContextStartedEvent(ContextStartedEvent event) {
        log.info("# ContextStartedEvent");
    }

    @EventListener(ContextStoppedEvent.class)
    public void onContextStoppedEvent(ContextStoppedEvent event) {
        log.info("# ContextStoppedEvent");
    }

    @EventListener(ContextClosedEvent.class)
    public void onContextClosedEvent(ContextClosedEvent event) {
        log.info("# ContextClosedEvent");
    }

    @EventListener(ApplicationContextInitializedEvent.class)
    public void onApplicationContextInitializedEvent(ApplicationContextInitializedEvent event) {
        log.info("# ApplicationContextInitializedEvent");
    }

    @EventListener(ApplicationEnvironmentPreparedEvent.class)
    public void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
        log.info("# ApplicationEnvironmentPreparedEvent");
    }

    @EventListener(ApplicationPreparedEvent.class)
    public void onApplicationPreparedEvent(ApplicationPreparedEvent event) {
        log.info("# ApplicationPreparedEvent");
    }

    @EventListener(WebServerInitializedEvent.class)
    public void onApplicationStartedEvent(WebServerInitializedEvent event) {
        log.info("# WebServerInitializedEvent");
    }

    @EventListener(ApplicationStartedEvent.class)
    public void onApplicationStartedEvent(ApplicationStartedEvent event) {
        log.info("# ApplicationStartedEvent");
    }

    @EventListener(ApplicationReadyEvent.class)
    public void onApplicationReadyEvent(ApplicationReadyEvent event) {
        log.info("# ApplicationReadyEvent");
    }

    @EventListener(ApplicationFailedEvent.class)
    public void onApplicationFailedEvent(ApplicationFailedEvent event) {
        log.info("# ApplicationFailedEvent");
    }

    @EventListener(ApplicationStartingEvent.class)
    public void onApplicationStartingEvent(ApplicationStartingEvent event) {
        log.info("# ApplicationStartingEvent");
    }
}

그리고 스프링 부트를 시작해보자.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

실행결과

INFO 4613 --- [           main] com.example.EventHandlers                : # ContextRefreshedEvent
INFO 4613 --- [           main] com.example.Application                  : Started Application in 1.339 seconds (JVM running for 1.823)
INFO 4613 --- [           main] com.example.EventHandlers                : # ApplicationStartedEvent
INFO 4613 --- [           main] com.example.EventHandlers                : # ApplicationReadyEvent
INFO 4613 --- [           main] com.example.EventHandlers                : # ContextStartedEvent

다음은 context를 시작하고 종료하는 코드를 넣어보자.

ConfigurableApplicationContext 를 통해 start() 후에 바로 stop()을 호출한다.

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
        context.start();
        context.stop();
    }
}

실행결과

INFO 6127 --- [           main] com.example.EventHandlers                : # WebServerInitializedEvent
INFO 6127 --- [           main] com.example.EventHandlers                : # ContextRefreshedEvent
INFO 6127 --- [           main] com.example.Application                  : Started Application in 1.32 seconds (JVM running for 1.734)
INFO 6127 --- [           main] com.example.EventHandlers                : # ApplicationStartedEvent
INFO 6127 --- [           main] com.example.EventHandlers                : # ApplicationReadyEvent
INFO 6127 --- [           main] com.example.EventHandlers                : # ContextStartedEvent
INFO 6127 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
INFO 6127 --- [           main] com.example.EventHandlers                : # ContextStoppedEvent
INFO 6127 --- [ionShutdownHook] com.example.EventHandlers                : # ContextClosedEvent

참고

https://reflectoring.io/spring-boot-application-events-explained/

https://www.baeldung.com/spring-context-events

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유