ApplicationContextEvent

appti·2024년 3월 13일
0

분석

목록 보기
9/23

정의

ApplicationContextEvent는 ApplicationContext의 생명 주기에 따라 발생시키는 이벤트입니다.

개발자가 스프링 이벤트를 직접 사용하는 경우 @EventListener와 함께 ApplicationEvent를 사용하지만, ApplicationContextEvent는 스프링 내부적으로 발행하는 이벤트이기 때문에 개발자가 직접 사용할 일은 희박합니다.

위와 같이 ApplicationContextEvent를 확장한 클래스는 다음과 같이 4종류가 존재합니다.

  • ContextRefreshedEvent
  • ContextClosedEvent
  • ContextStartedEvent
  • ContextStoppedEvent

여기서 Started, Stopped의 경우 명시적으로 AbstractApplicationContext에서 stop(), start()를 명시적으로 호출해야 하기 때문에 잘 사용되지 않습니다.

그러므로 Refreshed, Closed 호출 시 이를 처리하는 Listener만 살펴보고 나머지는 단순히 어떤 상황에서 호출되는지만 확인하겠습니다.

이벤트 발행

스프링에서는 위와 같이 ApplicationContext에서 관리하고 있는 ApplicationEventMulticaster를 통해 이벤트를 발행합니다.

특별한 설정을 하지 않는 이상 SimpleApplicationEventMulticaster를 사용합니다.

만약 ApplicationContext에 ApplicationEventMulticaster를 초기화하지 않은 상태라면 earlyApplicationEvents에 컬렉션이 초기화된 상태가 됩니다.
그러므로 ApplicationContext 생명 주기에 의해 발생한 이벤트를 ApplicationContext에서 관리할 수 있습니다.

이렇게 저장한 earlyApplicationEvents는 AbstractApplicationContext.refresh()에서 onRefresh() 호출 후, finishBeanFactoryInitialization()으로 인해 빈 인스턴스를 생성하기 전 Listener를 등록하는 registerListeners()에서 발행됩니다.

이 시점에서는 ApplicationEventMulticaster가 초기화하므로, 그 직후 이벤트를 발행한다고 볼 수 있습니다.

ContextRefreshedEvent

ApplicationContext를 refresh할 때 발행하는 이벤트입니다.
ApplicationContext가 close되지 않았다면 계속 발행이 가능합니다.

다만, 일반적으로는 ApplicationContext.refresh()가 모두 수행된 이후에 단 한 번만 발행됩니다.
만약 애플리케이션 동작 도중 ApplicationContext의 설정(빈 구성 등)이 변경되는 경우에는 다시 ContextRefreshEvent가 발행될 수 있지만, 흔한 상황은 아니기 때문에 한 번만 수행한다고 봐도 무방합니다.

AbstractApplicationContext.refresh()를 모두 수행하고, 후처리를 수행하는 finishRefresh()에서 이벤트를 발행하고 있음을 확인할 수 있습니다.

이벤트 처리 Listener

ApplicationContext에 등록된 Listener 중 ContextRefreshedEvent 이벤트를 처리하는 Listener는 다음과 같습니다.

  • SharedMetadataReaderFactoryContextInitializer$SharedMetadataReaderFactoryBean
    • MetadataReaderFactory의 캐시를 삭제합니다.
  • ConditionEvaluationReportLoggingListener$ConditionEvaluationReportListener
    • 빈으로 등록할 후보군들의 Conditional 결과를 로그로 출력합니다.
  • ClearCachesApplicationListener
    • 빈을 등록하던 과정 중 리플렉션, 클래스 로더에 저장했던 캐시를 삭제합니다.
  • ScheduledAnnotationBeanPostProcessor
    • ApplicationContext의 스케줄링 기능을 활성화합니다.
  • ResourceUrlProvider
    • 애플리케이션 리소스 매핑 정보를 최신 상태로 갱신합니다.

ContextClosedEvent

ApplicationContext.close()를 호출했을 때 발행하는 이벤트입니다.

이 이벤트가 발행되었다는 것은 ApplicationContext가 완전히 종료되었고, 재시작 할 수 없는 상태가 되었음을 의미합니다.

위와 같이 AbstractApplicationContext.doClose() 수행 시 이벤트를 발행한 뒤 나머지 작업을 수행하고 있음을 확인할 수 있습니다.

이벤트 처리 Listener

  • SpringApplicationShutdownHook$ApplicationContextClosedListener
    • SpringApplicationShutdownHook에서 ApplicationContext의 상태를 contexts에서 closedContexts로 변경합니다.
  • ParentContextCloserApplicationListener.ContextCloserListener
    • ApplicationContext가 닫힐 때, 활성화되어 있는 자식 ApplicationContext도 같이 종료(close) 합니다.
  • LoggingApplicationListener
    • LoggingSystem을 정리(CleanUp) 합니다.

ContextStartedEvent

ApplicationContext가 중지(stopped)된 후, 명시적으로 AbstractApplicationContext.start()를 호출했을 때 발행되는 이벤트입니다.

명시적으로 AbstractApplicationContext.stop()이 호출된 이후에 명시적으로 AbstractApplicationContext.start()를 호출해야만 발행됩니다.

AbstractApplicationContext.start() 호출 시 발행됩니다.

ContextStoppedEvent

동작 중인 ApplicationContext를 중지한 후 발행되는 이벤트입니다.

AbstractApplicationContext.stop() 호출 시 발행됩니다.

profile
안녕하세요

0개의 댓글