개요

옵저버 패턴의 구현체로서, 이벤트 기반의 프로그래밍을 할 때 유용한 인터페이스.
 

실습을 위한 주요 구성 요소

퍼블리셔, 이벤트, 이벤트핸들러
 

이벤트

  • 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(this100));
    }
}
@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){
        //
    }
}