개요
옵저버 패턴의 구현체로서, 이벤트 기반의 프로그래밍을 할 때 유용한 인터페이스.
실습을 위한 주요 구성 요소
퍼블리셔, 이벤트, 이벤트핸들러
이벤트
- ApplicationEvent 상속
public
class
MyEvent
extends
ApplicationEvent {
private
int
data;
public
MyEvent(Object source){
super
(source);
}
public
MyEvent(Object source,
int
data){
super
(source);
this
.data=data;
}
public
int
getData(){
return
data;
}
}
- 스프링 4.2부터는 "ApplicationEvent" 클래스를 상속 받지 않아도 이벤트로 사용 가능하다.
용어
비침투성(non-invasive, transparent)이란 스프링 프레임 워크의 코드가 직접 작성하는 코드 layer에는 노출되지 않는 것이다.
이벤트 발생시키는 방법
- ApplicationEventPublisher.publishEvent()
@Component
public
class
AppRunner
implements
ApplicationRunner {
@Autowired
ApplicationEventPublisher publishEvent;
@Override
public
void
run(ApplicationArguments args)
throws
Exception {
publishEvent.publishEvent(
new
MyEvent(
this
,
100
));
}
}
@Component를 추가하여 Bean으로 만든다.
이벤트 처리하는 방법
- ApplicationListner<이벤트> 구현한 클래스 만들어서 빈으로 등록한다.
- 스프링4.2부터는 @EventListener를 사용하면 interface를 상속할 필요는 없다.
//스프링 4.2 이전
@Component
public
class
MyEventHandler
extends
ApplicationListener<MyEvent> {
private
int
data;
@Override
public
void
onApplicationEvent(MyEvent myEvent) {
System.out.println(event.getData());
}
}
//스프링 4.2 이후
@Component
public
class
MyEventHandler{
@EventListener
public
void
handle(MyEvent event){
System.out.println(event.getData());
}
}
- 기본적으로는 synchronized : 다른 Handler를 두어 실행하면 별개의 설정이 없을 경우 동일 스레드 실행. 순서는 랜덤.
- 순서를 정하고 싶다면 @Order와 함께 사용한다.
@Component
public
class
MyEventHandler{
@EventListener
@Order
(Ordered.HIGHEST_PRECEDENCE)
// (HIGHEST_PRECEDENCE+1) 보다 앞서 실행
public
void
handle(MyEvent event){
System.out.println(event.getData());
}
}
- 비동기적으로 실행하고 싶다면 @Async와 함께 사용한다.
@Component
public
class
MyEventHandler{
@EventListener
@Async
public
void
handle(MyEvent event){
System.out.println(event.getData());
}
}
이 경우는 비동기 실행이므로 스레드가 분리되며, @Order는 따라서 의미가 없다. @EnableAsync를 App class에 annotation으로 추가하여야 한다.
스프링이 제공하는 기본 이벤트
- ContextRefreshedEvent: ApplicationContext를 초기화한 후 리프레시 했을 때 발생.
- ContextStartedEvent: ApplicationContext를 start()하여 라이브사이클 빈들이 시작 신호를 받은 시점에 발생
- ContextStoppedEvent: ApplicationContext를 stop()하여 라이브사이클 빈들이 시작 신호를 받은 시점에 발생
- ContextClosedEvent: ApplicationContext를 close()하여 싱글톤 빈이 소멸되는 시점에 발생
- 아래 코드처럼 각각 handling할 수 있다.
@Component
public
class
MyEventHandler{
@EventListener
@Async
public
void
handle(MyEvent event){
//
}
@EventListener
@Async
public
void
handle(ContextRefreshedEvent event){
//
}
@EventListener
@Async
public
void
handle(ContextClosedEvent event){
//
}
}