이벤트 프로그래밍에 필요한 인터페이스 제공. 옵저버 패턴 구현체.
ApplicationContext extends ApplicationEventPublisher
이벤트 만들기
public class MyEvent extends ApplicationEvent {
private int data;
public MyEvent(Object source) {
super(source);
}
public MyEvent(Object source, int data) {
this.source = source;
this.data = data;
}
public int getData(){
return data;
}
}
이 이벤트를 발생시키는 기능을 ApplicationContext가 가지고 있다.
이벤트 발생 시키는 방법
@Component
public class AppRunner implements ApplicationRunner {
/*
@Autowired
ApplicationContext applicationContext;
*/
@Autowired
ApplicationEventPublisher publishEvent;
@Override
public void run(ApplicationArguments args) throws Exception {
publishEvent.publishEvent(new MyEvent(this, 100));
}
}
이 이벤트를 처리하려면 이벤트 핸들러가 필요하고, 이벤트 핸들러는 빈으로 등록되어야 한다.
이벤트 처리하는 방법
@Component
public class MyEventHandler implements ApplicationListener<MyEvent> {
@Override
public void onApplicationEvent(MyEvent myEvent) {
System.out.println("이벤트 받았다. 데이터는 " + myEvent.getData());
}
}
이벤트를 발생시킨 소스 확인하기
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;
}
}
@Component
public class MyEventHandler {
@EventListener
public void handle(MyEvent event){
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
EventHandler가 여러가지 있다고 가정해보자.
@Component
public class MyEventHandler {
@EventListener
public void handle(MyEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
@Component
public class AnotherHandler {
@EventListener
public void handler(MyEvent myEvent){
System.out.println(Thread.currentThread().toString());
System.out.println("Another " + myEvent.getData());
}
}
그러면 이 두 핸들러 모두 실행될 것이다. 기본적으로는 순차적으로 실행된다(synchronized). 이를 확인해보려면 스레드의 이름을 찍어보면 되는데, 둘 다 main 스레드에서 실행된다.
순차적으로 실행되는 경우에는 Sequence를 지정해 줄 수 있다.
@Component
public class AnotherHandler {
@EventListener
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
public void handler(MyEvent myEvent){
System.out.println(Thread.currentThread().toString());
System.out.println("Another " + myEvent.getData());
}
}
@Component
public class MyEventHandler {
@EventListener
@Order(Ordered.HIGHEST_PRECEDENCE)
public void handle(MyEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
순서는 보장되지 않는다. 각각의 쓰레드 풀에서 따로 실행됨
@SpringBootApplication
@EnableAsync
public class Springtest6Application {
public static void main(String[] args) {
SpringApplication.run(Springtest6Application.class, args);
}
}
@Component
public class AnotherHandler {
@EventListener
@Async
public void handler(MyEvent myEvent){
System.out.println(Thread.currentThread().toString());
System.out.println("Another " + myEvent.getData());
}
}
@Component
public class MyEventHandler {
@EventListener
@@Async
public void handle(MyEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
스프링이 제공하는 기본 이벤트 (ApplicationContext) 관련
@Component
public class MyEventHandler {
@EventListener
@Async
public void handle(MyEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("이벤트 받았다. 데이터는 " + event.getData());
}
@EventListener
@Async
public void handle(ContextRefreshedEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("ContextRefreshedEvent");
//var applicationContext = event.getApplicationContext()
}
@EventListener
@Async
public void handle(ContextClosedEvent event){
System.out.println(Thread.currentThread().toString());
System.out.println("ContextClosedEvent");
//var applicationContext = event.getApplicationContext()
}
}
참고