Spring

Spring Framework_ApplicationEventPublisher,@EventListener

검은고양이개발자 2023. 3. 3. 00:14
반응형


ApplicationEventPublisher Interface



Spring Framework는 이벤트 기반 프로그래밍(Event-driven programming)을 지원합니다. 

 

이벤트 기반 프로그래밍은 특정 이벤트 발생 시 해당 이벤트를 처리하는 동작을 하는 방식입니다. 

Spring Framework에서는 이벤트 발생 시 특정 작업을 수행하는 기능을 ApplicationEventPublisher와 @EventListener를 통해 제공합니다.

 

@FunctionalInterface
public interface ApplicationEventPublisher {

   /**
    * Notify all <strong>matching</strong> listeners registered with this
    * application of an application event. Events may be framework events
    * (such as ContextRefreshedEvent) or application-specific events.
    * <p>Such an event publication step is effectively a hand-off to the
    * multicaster and does not imply synchronous/asynchronous execution
    * or even immediate execution at all. Event listeners are encouraged
    * to be as efficient as possible, individually using asynchronous
    * execution for longer-running and potentially blocking operations.
    * @param event the event to publish
    * @see #publishEvent(Object)
    * @see org.springframework.context.event.ContextRefreshedEvent
    * @see org.springframework.context.event.ContextClosedEvent
    */
   default void publishEvent(ApplicationEvent event) {
      publishEvent((Object) event);
   }

   /**
    * Notify all <strong>matching</strong> listeners registered with this
    * application of an event.
    * <p>If the specified {@code event} is not an {@link ApplicationEvent},
    * it is wrapped in a {@link PayloadApplicationEvent}.
    * <p>Such an event publication step is effectively a hand-off to the
    * multicaster and does not imply synchronous/asynchronous execution
    * or even immediate execution at all. Event listeners are encouraged
    * to be as efficient as possible, individually using asynchronous
    * execution for longer-running and potentially blocking operations.
    * @param event the event to publish
    * @since 4.2
    * @see #publishEvent(ApplicationEvent)
    * @see PayloadApplicationEvent
    */
   void publishEvent(Object event);

}

<코드 1>

ApplicationEventPublisher는 이벤트를 발생시키는 인터페이스입니다. 

이 인터페이스를 구현한 객체는 이벤트를 발생시키는 메서드인 publishEvent(Object event)를 제공합니다.

이 메소드는 인자로 전달받은 이벤트를 등록된 리스너에게 전달하고, 이벤트가 처리되는 동안 다른 작업을 처리할 수 있도록 비동기적으로 처리됩니다.

 

 

 

 

 

 

 

 

 

 

@EventListener



@EventListener는 이벤트를 처리하는 어노테이션입니다. 

 

해당 어노테이션을 붙인 메서드는 등록된 이벤트 발생 시 자동으로 호출됩니다. 

@EventListener 어노테이션은 메서드의 인자로 전달받는 이벤트 객체를 인식하고, 

이벤트 객체의 타입에 따라 이벤트 발생 시 해당 메서드를 자동으로 호출합니다.

 

 

@EventListener
public void listen(MemberRegistrationEvent event) throws Exception {
    try {
        // 전송할 메시지를 생성했다고 가정.
        String message = "이것은 인텔리제이에서 보내는 메시지";
        emailSender.sendEmail("wjrmffldgl@naver.com",event.getMember().getEmail(),message);
    }catch (AuthenticationFailedException e) {
        log.error("Failed to send email: authentication failed");
        Member member = event.getMember();
        memberService.deleteMember(member.getMemberId());
    } catch (MailSendException e) {
        e.printStackTrace();
        log.error("MailSendException: rollback for Member Registration:");
        Member member = event.getMember();
        memberService.deleteMember(member.getMemberId());
    }
}

<코드 2>

 

 

 

 

 

 

 

@Transactional
@Service
public class MemberService {
    private final MemberRepository memberRepository;
    private final ApplicationEventPublisher publisher;
    

    public MemberService(MemberRepository memberRepository,
                         ApplicationEventPublisher publisher
                         ) {
        this.memberRepository = memberRepository;
        this.publisher = publisher;
    }
    
    public Member createMember(Member member) {
        verifyExistsEmail(member.getEmail());
        Member savedMember = memberRepository.save(member);

        publisher.publishEvent(new MemberRegistrationEvent(savedMember));
        return savedMember;
    }

<코드 3>

 

 

 

 

<코드 3>에서 보면 ApplicationEventPulisher 를 객체화한 publisher는 publishEvent() 메서드를 쓸 수 있는데

이 메소드를 사용하면 @EventListener 가 붙은 메서드가 실행됩니다.

 

이를 통해 ApplicationEventPublisher와 @EventListener를 함께 사용해 이벤트 기반 프로그래밍을 구현할 수 있습니다. 

 

예를 들어, 회원 가입 시 이벤트를 발생시켜서 이벤트 리스너가 해당 이벤트를 처리하도록 할 수 있습니다. 

회원 가입 이벤트가 발생하면 이벤트 객체를 생성하고 ApplicationEventPublisher를 통해 이벤트를 발생시킵니다. 

이벤트 리스너는 @EventListener 어노테이션을 통해 이벤트 객체를 인식하고, 해당 이벤트를 처리하는 메서드를 구현할 수 있습니다.

 

이러한 이벤트 기능은 애플리케이션 내에서 여러 컴포넌트들이 서로 독립적으로 작동하면서도, 이벤트를 통해 연결되어 상호작용할 수 있도록 만들어주기 때문에 이로 인해 애플리케이션의 유지보수성과 확장성이 높아지며, 복잡한 프로세스를 간단하게 처리할 수 있게 됩니다.

하지만 ApplicationEventPublisher와 @EventListener를 사용할 때에는 주의해야 할 점이 있는데, 그건

비동기적으로 처리되기 때문에 순서가 보장되지 않을 수 있다는 점입니다.

따라서, 이벤트 발생 시 다른 작업이 필요한 경우에는 적절한 처리를 해주어야 합니다.





반응형