사진찍는 개발자 블로그

💻 개발/Java

Guava EventBus 간단 사용법

개발자영준 2020. 8. 7. 23:48

Guava 라이브러리의 EventBus를 사용하면 굉장히 쉽고 간단하게 Publish/Subscribe 방식의 이벤트 처리를 구현할 수 있다. 회사 프로젝트 코드에서도 많이 사용하고 있어서 간단하게 정리해봤다.

 

EventBus 생성

EventBus는 이벤트를 처리할 각 이벤트 리스너를 등록하고 각 리스너에게 이벤트를 전파하는 역할을 수행한다. EventBus 객체는 다음과 같이 생성자를 호출해서 간단하게 생성할 수 있다.

EventBus eventBus = new EventBus();

혹은 생성자 파라미터에 문자열 값을 넘겨서 이벤트버스의 이름을 지정할 수 있다.

EventBus eventBus = new EventBus("myEventBus");

참고로 이름을 설정하지 않으면 기본 이름은 "default"로 설정된다. 만약 스프링 환경에서 사용한다면 이벤트버스를 빈으로 등록해 사용하면 된다.

 

이벤트 리스너 생성 및 등록

이벤트 리스너는 이벤트를 받아 처리하는 객체다. 이벤트 리스너를 만들기 위해 특정 interface를 구현할 필요는 없다. 아래 코드처럼 이벤트를 처리하는 메서드를  구현하고 @Subscibe (com.google.common.eventbus.Subscribe) 어노테이션을 달아주면 해당 메서드가 이벤트 핸들러 메서드의 역할을 하게된다. 여기서는 단순하게 String으로된 이벤트를 처리하는 리스너를 예로 들었다.

public class StringEventListener {
    @Subscribe
    public void handle(String event) {
        System.out.println("string event received : " + event);
    }
}

이벤트 리스너를 만들기 위해서 특정 타입을 강요하지 않기 때문에 상당히 유연한 장점이 있다. 단 아래 사항을 주의해서 구현해야 한다.

  • 이벤트 객체는 반드시 primitive 타입이 아닌 reference 타입의 객체여야 한다.
  • 핸들러 메서드는 이벤트 객체를 받는 단 하나의 파라미터만 존재해야 한다.
  • 핸들러 메서드의 시그니처는 public void methodName(Object event) 형태여야 한다. 

이렇게 구현한 이벤트 리스너를 eventBus의 register() 메서드로 등록하게 되면 이벤트 구독을 할 수 있는 상태가 된다.

// 이벤트 리스너를 이벤트버스에 등록
eventBus.register(new StringEventListener());

 

이벤트 발행하기

EventBus의 post() 메서드로 이벤트를 발행할 수 있다. 이벤트 버스에 이벤트를 발행하면 해당 이벤트를 구독하고 있는 이벤트 리스너에서 이벤트를 받아 처리하게 된다.

@Test
public void postEvent() {
    EventBus eventBus = new EventBus("myEventBus");
    eventBus.register(new StringEventListener());
    
    eventBus.post("TEST EVENT");
}

// 출력
// string event received : TEST EVENT

 

커스텀 이벤트 발행하기

String, Integer, Long 같은 기본 타입 뿐만 아니라 직접 이벤트 객체를 정의해서 발행, 구독 하는것도 가능하다. 

먼저 커스텀 이벤트를 하나 정의한다.

@Getter
@AllArgsConstructor
public class MyEvent {
    private String value;
}

커스텀 이벤트를 처리할 이벤트 리스너도 하나 만든다.

public class MyEventListener {
    @Subscribe
    public void handle(MyEvent myEvent) {
        System.out.println("MyEvent : " + myEvent.getValue());
    }
}

앞의 예제와 마찬가지로 이벤트 버스에 리스너를 등록하여 커스텀 이벤트를 발행 할 수 있다.

public class EventBusTest {
    public static void main(String[] args) {
        EventBus eventBus = new EventBus("myEventBus");

        eventBus.register(new MyEventListener());

        eventBus.post(new MyEvent("test"));
    }
}

// MyEvent : test

 

Dead Event 처리하기

어떤 이벤트가 발행 되었는데 만약 이를 처리할 수 있는 이벤트 리스너가 없다면, 이벤트 버스는 이를 죽은 이벤트로 간주하고 DeadEvent 라는 클래스로 감싸서 발행한다. 아래처럼 DeadEvent 처리를 위한 이벤트 리스너를 등록하면 이렇게 죽은 이벤트들도 놓치지 않고 다시 처리할 수 있다. 

public class DeadEventListener {
    @Subscribe
    public void handle(DeadEvent deadEvent) {
        System.out.println("dead event posted");
        System.out.println("dead event : " + deadEvent.getEvent());
        System.out.println("dead event source : " + deadEvent.getSource());
    }
}
  • deadEvent.getEvent() : 발행된 이벤트 객체
  • deadEvent.getSource() : 이벤트가 발행된 이벤트 버스
public class EventBusTest {
    public static void main(String[] args) {
        EventBus eventBus = new EventBus("myEventBus");

        eventBus.register(new MyEventListener());
        eventBus.register(new DeadEventListener());

        eventBus.post(new MyEvent("test"));
        eventBus.post("this is dead event");
    }
}

위의 코드를 보면 마지막에 String 타입의 이벤트를 발행하지만 이를 처리할 수 있는 리스너가 등록되지 않았기 때문에 DeadEvent로 처리가 된다.