8.ApplicationEventPublisher

ApplicationContext가 상속받고있는 ApplicationEventPublisher인터페이스로서 이는 이벤트 프로그래밍에 필요한 인터페이스이다.

MyEvent를 만들고

MyEvent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class MyEvent implements 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;
}
}

이벤트를 발생시켜보자.

AppRunner.java
1
2
3
4
5
6
7
8
public class AppRunner implements ApplicationRunner{
@Autowired
ApplicationEventPublisher publishEvent; // ApplicationContext로 해도 가능하긴함
...run(){
//이벤트 발생
publishEvent.publishEvent(new MyEvent (this,100));
}
}

이벤트가 발생했을 때 해당이벤트를 받는 핸들러는 빈으로 등록되어 있어야 한다.
이벤트를 받는 핸들러를 정의하자.

MyEventHandler.java
1
2
3
4
5
6
7
8
9
@Component
public class MyEventHandler implements ApplicationListener<MyEvent>{

@Override
public void onApplicationEvent(MyEvent event) {
print("핸들러가 받은 이벤트의 데이터"+event.getData());
}

}

4.2 이후부터는 위와같이 불편하게 하지 않아도 된다.

Event 클래스는 ApplicationEvent를 구현하지 않아도 된다.

MyEvent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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 source;
}

public int getData() {
return data;
}
}

위와같은 소스는 스프링이 추구하는 비침투성(스프링 코드가 사용자 코드에 들어가지 않는것)을 구현한것

핸들러도 ApplicationListener 인터페이스를 구현하지 않아도 되게 되었지만 빈으로는 등록해야 한다.

MyEventHandler.java
1
2
3
4
5
6
7
8
9
@Component
public class MyEventHandler{

@EventListener
public void myhandle(MyEvent event) {
print("핸들러가 받은 이벤트의 데이터"+event.getData());
}

}

여러개의 핸들러가 하나의 이벤트를 핸들 할 경우?
동일한 쓰레드 내에서 순차적으로 실행된다. 순서는 보장되지 않으며 순서를 보장하고 싶으면 다음과 같이 @Order을 주면 된다.

1
2
3
4
5
6
@EventListener
@Order(Ordered.HIGHEST_PRECEDENCE) // @Order(Ordered.HIGHEST_PRECEDENCE)+3
//낮은것이 먼저 실행됨
public void myhandle(MyEvent event) {
print("핸들러가 받은 이벤트의 데이터"+event.getData());
}

비동기적으로 실행하고 싶을 때는?
순서는 보장안된다. 이땐 order도 무의미해짐.

1
2
3
4
5
6
7
@EventListener
@Async
//낮은것이 먼저 실행됨
public void myhandle(MyEvent event) {
print("핸들러가 받은 이벤트의 데이터"+event.getData());
}
``

그리고 Application 클래스에 @EnableAsync 어노테이션을 붙여준다.
이 외에도 쓰레드 풀에 관련한 설정을 더 해야되는데 비동기 관련된 수업이 아니므로 건너뛴다.

스플링이 기본적으로 제공하는 이벤트들을 확인해보자
ContextRefreshedEvent: ApplicationContext를 초기화 했더나 리프래시 했을 때 발생.
ContextStartedEvent: ApplicationContext를 start()하여 라이프사이클 빈들이 시작 신호를 받은 시점에 발생.
ContextStoppedEvent: ApplicationContext를 stop()하여 라이프사이클 빈들이 정지 신호를 받은 시점에 발생.
ContextClosedEvent: ApplicationContext를 close()하여 싱글톤 빈 소멸되는 시점에 발생.
RequestHandledEvent: HTTP 요청을 처리했을 때 발생.

1
2
3
4
5
@EventListener
public void myhandle(ContextRefreshedEvent event) {
print("핸들러가 받은 이벤트의 데이터"+event.getData());
}

이벤트는 위와같이 확인할 수 있다는점을 잊지말자.

Share