IoC 컨테이너 8부 - ApplicationEventPublisher
참고문헌
ApplicationEventPublisher
- 이벤트 프로그래밍에 필요한 인터페이스 제공
-
옵저버 패턴으로 구현한 구현체
- ApplicationContext extends ApplicationEventPublisher
- publishEvent(ApplicationEvent event)
이벤트 발생시키는 방법
- ApplicationEventPublisher.publishEvent();
이벤트 처리하는 방법
- ApplicationListener<이벤트> 구현한 클래스 만들어서 빈으로 등록하기이벤트>
- 스프링 4.2부터는 @EventListener를 사용해서 빈의 메소드에 사용할 수 있다.
- 기본적으로는 synchronized
- 순서를 정하고 싶다면, @Order 와 함께 사용
- 비동기적으로 실행하고 싶다면 @Async 와 함께 사용
스프링이 제공하는 기본 이벤트
ContextRefreshedEvent
- ApplicationContext를 초기화 했더나 리프래시 했을 때 발생.
ContextStartedEvent
- ApplicationContext를 start()하여 라이프사이클 빈들이 시작 신호를 받은 시점에 발생.
ContextStoppedEvent
- ApplicationContext를 stop()하여 라이프사이클 빈들이 정지 신호를 받은 시점에 발생.
ContextClosedEvent
- ApplicationContext를 close()하여 싱글톤 빈 소멸되는 시점에 발생.
RequestHandledEvent
- HTTP 요청을 처리했을 때 발생.
예시 1 :스프링부트 4.2 이전
- MyEvent.java
public class MyEvent extends ApplicationContext { 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; } }
- AppRunner.java
@Component public class AppRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { applicationContext.publishEvent(new MyEvent(this, 100)); }
- MyEventHandler.java
@Component
public class MyEventHandler implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent event) {
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
}
예시 2: 스프링부트 4.2 이후
- 스프링의 클래스들을 implement하지 않아도 됨
- MyEvent.java
public class MyEvent { private int data; private Object source; public MyEvent(Object source, int data) { this.source = source; this.data = data; } public Object getSource() { return sourfce; } public int getData() { return data; } }
- AppRunner.java
@Component public class AppRunner implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { applicationContext.publishEvent(new MyEvent(this, 100)); }
- MyEventHandler.java
@Component
public class MyEventHandler {
@EventListnener
@Order(Ordered.HIGHEST_PRECEDENECE) // 자장 높은 우선순위를 부여. 가장 먼저 실행되게 됨
@Async //비동기 실행. DemospringApplication (루트 메인 자바클래스)에 @EnableAsynce를 붙여야 제대로 비동기로 작동함
public void handle(MyEvent event) {
System.out.println(Thread.currentThread().toString());
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
}
@Component
public class AnotherHandler {
@EventListnener
@Order(Ordered.HIGHEST_PRECEDENECE + 2) // 자장 높은 우선순위를 부여. 가장 먼저 실행되게 됨
public void handle(MyEvent event) {
System.out.println(Thread.currentThread().toString());
System.out.println("Another" + event.getData());
}
}
예시 3 : 스프링이 제공하는 기본 이벤트들
- 하나의 자바파일에 여러개의 이벤트 핸들러를 설정해도 됨
- MyEventHandler.java
@Component public class MyEventHandler { @EventListnener @Async public void handle(MyEvent event) { System.out.println(Thread.currentThread().toString()); System.out.println(event.getData()); } @EventListnener @Async public void handle(ContextRefreshedEvent event) { System.out.println(Thread.currentThread().toString()); System.out.println("ContextRefreshedEvent"); } @EventListnener @Async public void handle(ContextClosedEvent event) { System.out.println(Thread.currentThread().toString()); System.out.println("ContextClosedEvent"); } }
- 결과 : 시작할 때, 종료될 때 이벤트들이 잘 처리됨