[Spring] EventListener
https://www.baeldung.com/spring-events
- ``kt ApplicationEventPublisher::publishEvent``로 pub 하고
- ``kt @EventListener``로 event 받아 처리하면 된다.
- 단 여기서 주의해야 할점! listener가 이벤트를 수신하는 것이 왠지 비동기로 이루어질 것 같지만, 기본적으로 동기식이다!
- 한 스레드가 pub한 다음, 해당 이벤트를 처리해야 하는 EventListener들을 돌면서 동기식으로 직접 리스너를 수행한다.
- By default, the listener is invoked synchronously. However, we can easily make it asynchronous by adding an @Async annotation. We just need to remember to enable Async support in the application.
Event와 순환 참조 문제
- Event를 사용하면 의존성을 끊을 수 있지만, 이렇게 의존성을 끊고 나서 반대방향 참조를 하게 되면 아래와 같은 에러를 마주칠 수 있다.
22:10:41.056 [WebSocketClient-SecureIO-2] ERROR o.s.w.s.a.s.StandardWebSocketHandlerAdapter - Closing session due to exception for StandardWebSocketSession[id=b85eba15-6fc8-6b1f-1c6d-bb93a2ccb1e7, uri=null]
org.springframework.beans.factory.BeanCreationNotAllowedException:
Error creating bean with name 'myContainer': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
- 상황?
- 종료 시, Listener가 Publisher를 참조하고 있으므로, Listener bean이 먼저 destroy 된다.
- Publisher가 Event를 publish하면, 이벤트를 수신할 bean을 가져오게 되는데, 이 때 최종적으로 `` DefaultSingletonBeanRegistry.getSingleton``를 사용하여 가져오게 된다. 이 메서드는 싱글턴을 반환하는데 없으면 생성 시도한다.
- Listener는 이미 destroy 되었으므로 생성 시도할텐데, shutdown으로 destruction phase에 진입했기 때문에 새로운 빈을 생성할 수 없다. 따라서 에러 발생하는 것.
/**
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName, ...
- 해결?
- 무시하거나, (어차피 종료 시에만 뜬다.)
- try-catch 처리하거나,
- application이 종료될 때, shutdown hook을 이용해서 flag 변수를 set하고 이를 체크하는 식으로 동작하거나. (✓)
도메인 모델에서 이벤트 직접 발행
https://namjug-kim.github.io/2020/03/24/spring-ddd-domain-event.html
https://www.baeldung.com/spring-data-ddd
'Java Stack > Spring' 카테고리의 다른 글
spring-webmvc 4.3.x와 5.x.x의 차이 - HttpMessageNotWritableException (0) | 2023.04.03 |
---|---|
spring-webmvc 에서 SpringBoot로 단계별로 전환하기 (0) | 2023.04.01 |
테스트 클래스를 일정 수 이상 묶어서 실행하면, 어느 정도 실행하다가 갑자기 JDBC Connection을 무한히 대기하는 현상 (0) | 2022.01.12 |
[Spring] DB 관련 : Mybatis CustomTypeHandler (0) | 2021.03.31 |
[Spring] WebClient (0) | 2021.03.14 |