@TransactionalEventListener
@transactionalEventListener 가
어떻게 이벤트를 인식하여 리스너를 실행하는지 알아보겠습니다.
Spring에서의 Spring event의 실행 단계 :
- 생성 주체에서 이벤트를 발생하면 이벤트 디스패처에게 전달
- 이벤트 디스패처가 이벤트 핸들러를 연결
- 이벤트 핸들러에서 이벤트에 담긴 데이터를 통해 원하는 기능을 실행
이번에 사용한 @TransactionalEventListener 는 적용할 메서드의 매개변수에 이벤트 객체를 정의해주면 지정한 이벤트가 발생했을 때 수신해서 처리할 수 있습니다. (이 점은@EventListener 와 동일)
또한 이벤트 발행자의 트랜잭션을 기준으로 이벤트 실행 시점을 조절할 때 사용할 수 있습니다.
option :
- AFTER_COMMIT (default) : 트랜잭션이 성공적으로 commit되었을 때 이벤트 실행
- AFTER_ROLLBACK : 트랜잭션이 rollback 되었을 때 이벤트 실행
- AFTER_COMPLETION : 트랜잭션이 마무리 되었을 때(commit or rollback) 이벤트 실행
- BEFORE_COMMIT : 트랜잭션의 커밋 전에 이벤트 실행
만약 리스너 코드를 아래와 같이 정의하게 되면
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void propagate(ScheduledEvent event){
log.info("RECEIVED EVENT!!!,event = {}",event);
log.info(TcpMessageCode.RECEIVED_TRANSACTIONAL_EVENT.getMessage());
nettyService.sendMessage(event.getMemberIdList());
}
정의해준 ScheduledEvent 객체를 이벤트 발행 시 같이 넘겨주어야 합니다.
매개변수가 일치하지 않으면 이벤트 디스패처가 핸들러를 연결할 수 없겠죠.
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
...
applicationEventPublisher.publishEvent(new ScheduledEvent(strings)); // 이벤트 리스닝 발동 o
applicationEventPublisher.publishEvent("event"); // 이벤트 리스닝 발동 x
Spring Event
Spring에는 이벤트를 발생시키고 처리하기 위한 인터페이스를 제공하고 옵저버 패턴의 구현체인 Functional Interface ApplicationEventPublisher 를 제공합니다.
이벤트를 발생시키기 위해 사용할 때는 ApplicationEventPublisher 는 이미 Bean으로 등록되어있기 때문에 Bean을 주입받아 사용합니다.
Spring Event의 특징
- 장점 - 각 모듈의 결합도를 낮추고 응집도를 높여주는 효과가 있습니다.
- 단점 - 코드량과 애플리케이션의 복잡도가 높아집니다
이벤트 핸들러는 Spring 4.2 이전에는 ApplicationListener<E> 클래스를 상속받아야 했습니다.
@Slf4j
@Component
@RequiredArgsConstructor
// ApplicationReadyEvent(스프링 컨테이너가 모두 띄워졌을 때 발생하는 이벤트)를 받는 리스너 클래스
public class NettyStartupTask implements ApplicationListener<ApplicationReadyEvent> {
private final NettyServerSocket nettyServerSocket;
@Override
public void onApplicationEvent( ApplicationReadyEvent event ) {
// 실행할 로직
}
}
하지만 이후부터는 이벤트 발생 시 처리하고 싶은 동작을 메서드에 정의하고, 해당 메서드에 어노테이션로 사용할 수 있습니다. (단, 메서드를 정의한 클래스는 Bean으로 등록되어야 합니다)
@EventListener
: 이벤트 핸들러를 구현하기 위해 사용하는 어노테이션입니다.
이 어노테이션을 사용하면 이벤트 리스너로 등록이 되고, 매개변수에 이벤트 객체를 정의하면 해당 이벤트가 발생했을 때 수신해서 처리할 수 있습니다.
그리고 TransactionalEventListener 와 달리 이벤트가 발생하자마자 실행됩니다.
사용 예시)
@EventListener
public void listener(String msg){
log.info("MSG : {}",msg);
}
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
...
eventPublisher.publishEvent("deleteMember event");
... 다른 로직 실행
출력결과 : MSG : deleteMember event … 다른 로직 실행