ApplicationListener는 함수형 인터페이스로, 스프링에서 이벤트를 처리하기 위한 인터페이스입니다.
제네릭에는 ApplicationEvent 타입을 명시해야 하며, onApplicationEvent를 통해 옵저버 패턴을 구현하는 방식입니다.
ApplicationListener는 다음과 같은 용도로 사용됩니다.
spring boot autoconfigurer 및 spring core의 META-INF/spring.factories에서 다음과 같이 SPI로 생성할 ApplicationListener를 확인할 수 있습니다.
이를 통해 스프링 부트는 ApplicationListener를 적극적으로 사용해 옵저버 패턴을 활용해 ApplicationContext를 초기화하는 것을 확인할 수 있습니다.
대표적인 예시는 ApplicationContextEvent입니다.
ContextRefreshed나 ContextClosedEvent는 각각 ApplicationContext가 refresh 되거나 close 될 때 발행되는 이벤트입니다.
이로 인해 설정을 최신화하거나, 자원을 반환하는 등 이벤트에 따라 다양한 기능을 수행합니다.
이는 발행된 이벤트를 통해 ApplicationListener가 빈들간의 정보를 교환하는 것이 아니라, 이벤트 처리 메커니즘을 통해 간접적으로 빈들 간의 정보 교환을 가능하게 하는 기능을 의미합니다.
예를 들어, 앞서 언급한 ContextRefreshed를 처리하는 ApplicationListener 중에 다음과 같은 Listener가 존재합니다.
이 두 Listener는 모두 캐시를 삭제합니다.
즉, Application refresh 과정 중에서 사용하던 캐시를 refresh가 끝난 시점에서 삭제하는 것입니다.
이는 ApplicationContext의 상태가 refresh가 끝난, 사용이 가능한 상태임을 ApplicationListener로 알린 것입니다.
개발자가 다양한 의도를 가지고 등록한 EventListener 또한 ApplicationListener에 속하게 됩니다.
주로 @EventListener를 통해 등록하게 될텐데, 이 때 EventListenerMethodProcessor가 @EventListener를 등록한 메서드를 별도의 ApplicationListener로 변환해 빈으로 등록합니다.
ApplicationListener는 기본적으로 AutoConfiguration에 의해 ApplicationContext에 일부 등록됩니다.
이후 AbstractApplicationContext.refresh() 과정 중 registerListeners()에 의해 ApplicationListener가 일차적으로 등록됩니다.
이벤트를 발행할 ApplicationEventMulticaster에 AutoConfiguration으로 인해 등록된 ApplicationListener를 빈으로 등록하고, 이후 등록된 BeanDefinition 중 ApplicationListener 타입인 BeanDefinition의 이름을 ApplicationEventMulticaster에 등록합니다.
이 시점에서는 아직 모든 BeanDefinition들이 인스턴스화 되지 않았기 때문에, 추후 refresh 과정이 진행되고 빈 인스턴스가 생성되면 그 때 이차적으로 처리됩니다.
ApplicationEventMulticaster에 이벤트를 처리할 ApplicationListener를 등록했으므로, 미리 발행된 이벤트인 earlyApplciationEvents를 모두 처리합니다.
ApplicationContext refresh 과정 이후 위와 같이 ApplicationListener가 등록된 것을 확인할 수 있습니다.
개발자가 임의로 등록한 @EventListener 또한 별도의 ApplicationListener로 변환되어 등록되어 있는 것을 확인할 수 있습니다.
빈 이름만 지정해놨던 ApplicationListener도 정상적으로 등록되어 있음을 확인할 수 있습니다.