오늘의 키워드
옵저버 패턴
이전에 옵저버 패턴에 대해서 공부는 한 적 있다.
구독자(observer)와 주체(subject)가 있을 때
subject의 데이터가 변경되면 구독자에게 알림을 전달하는 패턴이다.
headfirst-design-pattern-2206/Chapter02/je/옵저버.md at main · Developer-book-club/headfirst-design-pattern-2206
개발자 북클럽 (2기) - Headfirst Design Pattern 스터디. Contribute to Developer-book-club/headfirst-design-pattern-2206 development by creating an account on GitHub.
github.com
위는 이전에 정리했던 내용이다.
package headfirst.designpatterns.observer.simple;
import java.util.*;
public class SimpleSubject implements Subject {
private List<Observer> observers;
private int value = 0;
public SimpleSubject() {
observers = new ArrayList<Observer>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
//여기선 push방식을 사용했다.
//push방식 : 주제가 옵저버에게 상태를 알리는 방식
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(value);
}
}
public void setValue(int value) {
this.value = value;
notifyObservers();
}
}
위의 코드에서 보면 set 작업이 실행될 때 옵저버들 에게 알리는 메서드를 호출하는 것을 확인할 수 있다.
이벤트 리스너
이번에 알게된 내용은 이벤트 리스너가 해당 패턴을 사용한다고 한다.
goodsending-be/goodsending/src/main/java/com/goodsending/productmessage/event/listener/ProductMessageEventListener.java at dev
굿즈가 필요한 사람과 그렇지 않은 사람을 연결하는 실시간 경매 플랫폼. Contribute to goods-ending/goodsending-be development by creating an account on GitHub.
github.com
@Component
@RequiredArgsConstructor
public class ProductMessageEventListener {
private final ProductMessageServiceImpl productMessageService;
private final SimpMessagingTemplate messagingTemplate;
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleCreateProductMessageEvent(CreateProductMessageEvent event) {
ProductMessageDto productMessageDto = productMessageService.create(event);
// product에 메시지를 보낸다
messagingTemplate.convertAndSend(
DestinationPrefix.PRODUCT + productMessageDto.productId(), productMessageDto);
}
}
이전에 이벤트 리스너를 사용했을 때는 경매 입찰/낙찰이 되면 상품 채팅 메시지에 입찰/낙찰이 되었다는 메시지 이벤트를 발생시키고 싶어 위와같은 이벤트 리스너를 만든 적이 있다.
사용은 아래와 같이 ApplicationEventPublisher.pulishEvent()를 사용하여 진행했다.
import org.springframework.context.ApplicationEventPublisher;
@Service
@RequiredArgsConstructor
public class BidServiceImpl implements BidService {
...
private final ApplicationEventPublisher eventPublisher;
@Override
@Transactional
public BidResponse create(Long memberId, BidRequest request, LocalDateTime now) {
Product product = findProductWithOptimisticLock(request.productId());
... 입찰로직
// 입찰 메시지 이벤트 발행
eventPublisher.publishEvent(CreateProductMessageEvent.of(
memberId, request.productId(),
MessageType.BID,
request.bidPrice()));
return BidResponse.from(save);
}
여기서 구성요소는
- 이벤트 발생 주체(Subject): CreateProductMessageEvent
- Observer: ProductMessageEventListener
- Event Dispatcher (이벤트 전달자): Spring의 ApplicationEventPublisher
- notify()(=Observer 호출): publishEvent() → multicastEvent() 호출 후 @TransactionalEventListener 실행하는 것
이다.
TransactionalEventListenerMethodProcessor, ApplicationListenerMethodAdapter
해당 어뎁터에 onApplicationEvent(ApplicationEvent event)에서 트랜잭션 이벤트 리스너가 호출된다고 한다.
TransactionalEventListenerMethodProcessor가 리스너 등록을 해주는데 Spring이 실행될 때 @TransactionalEventListener가 붙은 모든 리스너를 찾아서 자동으로 등록해준다고 한다.
이부분은 나중에 좀더 알아봐야 겠다..
'TIL' 카테고리의 다른 글
[TIL] 2025.03.06 java 직렬화 serialVersionUID (0) | 2025.03.06 |
---|---|
[TIL] 2025.03.05 B트리 (0) | 2025.03.05 |
[TIL] 2025.02.28 아키텍처 (0) | 2025.02.28 |
[TIL] 2025.02.27 DDD (0) | 2025.02.27 |
[TIL] 2025.02.26 프로젝트 회고 (0) | 2025.02.26 |