[Spring] 이벤트 리스너

zini9188·2023년 3월 3일
0

Spring

목록 보기
28/33

이벤트 리스너

이벤트 리스너는 애플리케이션을 구현하는 과정에서 서로 다른 서비스간의 의존성이 발생하는 경우에 분리하여 의존성을 줄이기 위해 사용할 수 있다.

사진 출처

스프링 이벤트의 구성 요소와 동작 구현

스프링 이벤트는 event class와 이벤트를 발생시키는 event publisher, 이벤트를 받아들이는 event listener로 구성된다.

Spring Framework 4.2 이전에는 이벤트 클래스에서 ApplicationEvent를, 이벤트 리스너에서는 ApplicationListener를 구현해야 했지만, 4.2 이후부터는 애너테이션 설정으로 해결할 수 있다.

event class

@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;
    }
}

이벤트를 전달해주는 객체로 이벤트 실행의 기준점이 된다.

event publisher

@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() 메서드를 통해 이벤트 발의자를 정의한다.

event listener

@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 애너테이션을 사용하여 비동기식으로 이벤트를 처리할 수 있다.

profile
백엔드를 지망하는 개발자

0개의 댓글