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를 사용할 때에는 주의해야 할 점이 있는데, 그건
비동기적으로 처리되기 때문에 순서가 보장되지 않을 수 있다는 점입니다.
따라서, 이벤트 발생 시 다른 작업이 필요한 경우에는 적절한 처리를 해주어야 합니다.
'Spring' 카테고리의 다른 글
Java Spring_ @Mapping (0) | 2023.03.05 |
---|---|
Java Spring JPA (Cascade vs EntityManager.persist()) (0) | 2023.03.05 |
Spring을 이용해 이메일 보내는 방법 (0) | 2023.03.02 |
Spring Data JPA _ 페이징처리 (0) | 2023.02.22 |
Regex (정규 표현식) #Java로 regex 이용하기 (0) | 2023.02.19 |