post
)시킨 것과 동일한 쓰레드에서 Subscriber들이 이벤트를 처리한다.@Subscribe
애노테이션이 붙은 메소드는 public void methodName(Param onlyOneParam)
여야한다.@Subscribe
메소드가 있어도 된다.public class EventBusBasicExample { private static final Logger log = LoggerFactory.getLogger(EventBusBasicExample.class); public static class MessageListener { @Subscribe public void receive(String message) throws InterruptedException { log.info("Receiving message... {}", message); receiving(3, message); log.info("Done"); } private static void receiving(int count, String message) throws InterruptedException { for (int i = 0; i < count; i++) { log.info("... {}", message); TimeUnit.SECONDS.sleep(1L); } } } public static void main(String[] args) throws InterruptedException { log.info("### Starting Event Bus ###"); EventBus eventBus = new EventBus("sync"); ExecutorService executor = Executors.newFixedThreadPool(5); AsyncEventBus asyncEventBus = new AsyncEventBus("async", executor); asyncEventBus.register(new MessageListener()); eventBus.register(new MessageListener()); asyncEventBus.post("ASYNC event"); // eventBus.post를 먼저 실행하면 블로킹됨. eventBus.post("SYNC event"); log.info("### End ###"); if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { executor.shutdown(); } } }
결과.. EventBus
는 main
쓰레드에서 AsyncEventBus
는 쓰레드 풀(ExecutorService
)에서 subscribe 메소드 처리
@Subscribe
메소드는 멀티 쓰레드에서 동시 호출이 막혀있다하다. (synchronized
로 감싸져서 호출됨. 단, EventBus를 통하지 않고 별도의 코드로 직접 호출할 때 제외)@Subscribe
메소드에 @AllowConcurrentEvents 애노테이션을 붙여주면 여러 쓰레드에서 동시에 접근 가능해진다.@Subscribe
메소드는 모두 Thread-Safe 하게 작성하고 @AllowConcurrentEvents
어노테이션을 붙여줘야 성능 저하없이 사용가능하다.@AllowConcurrentEvents
이 존재하는 상태로 실행하면 receive
메소드가 멀티 쓰레드에서 동시에 실행된다. 따라서 로그가 여러쓰레드에서 뒤죽박죽 남는다.@AllowConcurrentEvents
를 주석 처리하면 receive
메소드가 특정 쓰레드에서만 점유되어 순차적으로 실행된다. 로그가 한 쓰레드씩 순차적으로 남는다.@Subscribe public void handleDeadEvent(DeadEvent deadEvent) { // do something }
@PostConstruct
로 등록하기 보다는 EventBus
객체 생성하는 설정 코드에서 Listener Bean을 생성해 바로 등록하는게 좋을 것 같다. @PostConstruct
로 등록시 어떤 것들이 등록돼 있는지 코드를 추적해 확인하기 어렵다.register
코드를 한 군데에 모아서 관리 편의성을 꾀하는게 좋아 보인다.@Subscribe
메소드는 항상 Thread-Safe 하게 작성하고 @AllowConcurrentEvents
를 붙인다.@Subscribe
메소드가 primitive type을 받아서는 안 된다. 항상 객체를 받아야 한다. 또한 파라미터는 항상 한 개여야 한다.EventBus
객체를 Singleton으로 한개만 생성해서 여러 이벤트들이 사용해도 되는가? → 그래도 된다. 이벤트별로 EventBus 객체를 분리하건, 단 한개의 통합 EventBus를 만들건 이벤트는 subscriber method의 파라미터에 의해 처리자가 결정되므로 작동에는 문제없다. 개발자가 적당히 선택해서 사용한다.