이벤트 리스너
이벤트 리스너는 애플리케이션을 구현하는 과정에서 서로 다른 서비스간의 의존성이 발생하는 경우에 분리하여 의존성을 줄이기 위해 사용할 수 있다.
스프링 이벤트의 구성 요소와 동작 구현
스프링 이벤트는 event class
와 이벤트를 발생시키는 event publisher
, 이벤트를 받아들이는 event listener
로 구성된다.
Spring Framework 4.2 이전에는 이벤트 클래스에서 ApplicationEvent를, 이벤트 리스너에서는 ApplicationListener를 구현해야 했지만, 4.2 이후부터는 애너테이션 설정으로 해결할 수 있다.
@Getter
public class MemberEvent {
private final Member member;
private final EmailSender emailSender;
private final MemberRepository memberRepository;
public MemberEvent(Member member, EmailSender emailSender, MemberRepository memberRepository) {
this.member = member;
this.emailSender = emailSender;
this.memberRepository = memberRepository;
}
}
이벤트를 전달해주는 객체로 이벤트 실행의 기준점이 된다.
@Service
public class MemberService {
private final MemberRepository memberRepository;
private final ApplicationEventPublisher publisher;
private final EmailSender emailSender;
public MemberService(MemberRepository memberRepository,
ApplicationEventPublisher publisher,
EmailSender emailSender) {
this.memberRepository = memberRepository;
this.publisher = publisher;
this.emailSender = emailSender;
}
public Member createMember(Member member) {
Member savedMember = memberRepository.save(member);
publisher.publishEvent(new MemberEvent(savedMember, emailSender, memberRepository));
return savedMember;
}
}
서비스에서 publishEvent()
메서드를 통해 이벤트 발의자를 정의한다.
@Slf4j
@Component
public class MemberEventListener {
@Async
@EventListener
public void sendMessage(MemberEvent memberEvent) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(() -> {
try {
log.debug("sendMessage");
memberEvent.getEmailSender().sendEmail("any email message");
} catch (Exception e) {
memberEvent.getMemberRepository().delete(memberEvent.getMember());
log.error("MailSendException happened: ", e);
throw new RuntimeException(e);
}
});
}
}
publisher에서 발행된 event를 사용하는 부분이다.
비동기 처리
@EnableAsync와 @Async 애너테이션을 사용하여 비동기식으로 이벤트를 처리할 수 있다.