반응형
Spring Framework의 `ApplicationEvent` 클래스는 Spring의 이벤트 발행 및 처리 메커니즘의 핵심입니다. 이 메커니즘을 통해 애플리케이션 내에서 이벤트를 발행하고, 이를 처리하는 리스너들을 등록할 수 있습니다. `ApplicationEvent`와 관련된 기능은 애플리케이션의 결합도를 낮추고, 코드의 모듈화를 증진시키는 데 유용합니다.
ApplicationEvent 클래스
- `ApplicationEvent`는 Java의 `java.util.EventObject`를 확장한 클래스입니다.
- Spring 4.2부터는 `ApplicationEvent`를 상속받지 않고, 어떠한 객체도 이벤트로 발행할 수 있습니다.
이벤트 발행
- 이벤트는 `ApplicationEventPublisher` 인터페이스를 통해 발행됩니다. 이 인터페이스는 보통 Spring의 `ApplicationContext`에 의해 제공됩니다.
- `publishEvent` 메소드를 사용하여 이벤트를 발행할 수 있습니다.
이벤트 리스닝
- 이벤트를 수신하기 위해 `ApplicationListener` 인터페이스를 구현하는 리스너를 만들 수 있습니다.
- Spring 4.2 이후부터는 `@EventListener` 어노테이션을 사용하여 메소드 레벨에서 이벤트 리스너를 쉽게 구현할 수 있습니다.
이벤트의 장점
- 결합도 감소
- 이벤트 발행자와 리스너 간의 결합도가 낮아집니다. 이벤트 발행자는 리스너의 구체적인 구현을 몰라도 됩니다.
- 유지보수성 향상
- 이벤트 기반의 코드는 유지보수하기 쉽고, 변경에 대한 영향을 최소화합니다.
- 비동기 처리
- @EventListener 가 적용된 이벤트 리스너는 동기적으로 수행됩니다.
- `@Async` 어노테이션을 사용하여 이벤트를 비동기적으로 처리할 수 있습니다.
주의사항
- 트랜잭션 관리
- 이벤트 리스너 내에서 수행되는 동작이 트랜잭션에 영향을 주지 않도록 주의해야 합니다.
- 성능 고려
- 많은 수의 이벤트 또는 복잡한 이벤트 처리 로직은 시스템의 성능에 영향을 줄 수 있습니다.
Spring의 `ApplicationEvent`는 애플리케이션 내에서 이벤트 기반 프로그래밍을 구현하는 데 매우 유용한 메커니즘을 제공합니다.
실습
이벤트 처리 순서는 다음과 같습니다.
- ApplicationEvent 객체를 생성하여 ApplicationEventPublisher를 통해 발행합니다.
- @EventListener가 지정된 메서드에서 ApplicationEvent를 소비합니다.
이벤트 클래스 정의
import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import java.util.Arrays;
import java.util.Objects;
@Getter
public class CustomEvent extends ApplicationEvent {
private final String eventType;
private final Object object;
private CustomEvent(String eventType, Object object){
super(object);
this.eventType = eventType;
this.object = object;
}
public static CustomEvent of(String eventType, Object object){
Arrays.asList(eventType, object).forEach(Objects::requireNonNull);
return new CustomEvent(eventType, object);
}
}
이벤트 퍼블리셔 정의
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class CustomEventPublisher {
private final ApplicationEventPublisher eventPublisher;
public void publish(String eventType, Object object){
eventPublisher.publishEvent(CustomEvent.of(eventType, object));
}
}
이벤트 리스너 정의
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class CustomEventConsumer {
private final Logger log = LoggerFactory.getLogger(CustomEventConsumer.class);
@Async
@EventListener
public void handleCustomEvent(CustomEvent event) {
log.info("EventType >> " + event.getEventType() + " , Object >> " + event.getObject());
}
}
@EnableAsync 적용
@SpringBootApplication
@EnableAsync
public class DemoApplication {
...
}
테스트 코드
@SpringBootTest
@ActiveProfiles("dev")
@ExtendWith(SpringExtension.class)
public class EventTester {
@Autowired
CustomEventPublisher customEventPublisher;
@Test
public void test(){
final String eventType = "TEST-EVENT-TYPE";
final String object = "TEST-OBJECT";
customEventPublisher.publish(eventType, object);
}
}
반응형
'[개발] 프레임워크 > Spring' 카테고리의 다른 글
[Spring FW] Filter (0) | 2023.12.10 |
---|---|
[Spring FW] Interceptor (0) | 2023.12.09 |
스프링 트랜잭션 (0) | 2023.11.26 |
Feign Client (2) | 2023.11.25 |
JPA N+1 문제 (0) | 2023.11.17 |