我就吃瓜(Guava): 事件总线EventBus

EventBus : 事件总线

  • EventBus 是Guava的事件处理机制,是观察者模式的优雅实现。

  • 使用Guava中的EventBus时,不需要再实现指定接口,只需要在指定的方法上实现@Subscribe注解即可。

  • 小栗子:

public class EventListener { //订阅者

    //@Subscribe保证有且只有一个输入参数,如果你需要订阅某种类型的消息,只需要在指定的方法上加上	            @Subscribe注解即可
    @Subscribe
    public void listen(OrderEvent event){
        System.out.println("receive message: "+event.getMessage());
    }

    /*
      一个subscriber也可以同时订阅多个事件
      Guava会通过事件类型来和订阅方法的形参来决定到底调用subscriber的哪个订阅方法
     */
    @Subscribe
    public void listen(String message){
        System.out.println("receive message: "+message);
    }
}

public class MultiEventListener { //订阅者

    @Subscribe
    public void listen(OrderEvent event){
        System.out.println("MultiEventListener receive msg: "+event.getMessage());
    }

    @Subscribe
    public void listen(String message){
        System.out.println("MultiEventListener receive msg: "+message);
    }
}

//发布-订阅模式中传递的事件,是一个普通的POJO类
public class OrderEvent {
    private String message;

    public OrderEvent(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
	
	//测试方法
    public static void main(String[] args) {
        EventBus eventBus = new EventBus("jack");
        /*
         如果多个subscriber订阅了同一个事件,那么每个subscriber都将收到事件通知
         并且收到事件通知的顺序跟注册的顺序保持一致
        */
        eventBus.register(new EventListener()); //注册订阅者
        eventBus.register(new MultiEventListener());
        eventBus.post(new OrderEvent("hello")); //发布事件
        eventBus.post(new OrderEvent("world"));
        eventBus.post("!");
        //out
        /**
         * receive message: hello
         * MultiEventListener receive msg: hello
         * receive message: world
         * MultiEventListener receive msg: world
         * receive message: !
         * MultiEventListener receive msg: !
         **/
    }

}

EventBus 观察

  • EventBus中的订阅者们和注册方法

private final SubscriberRegistry subscribers;

public void register(Object object) {
        this.subscribers.register(object);
}
void register(Object listener) {
    Multimap, Subscriber> listenerMethods = this.findAllSubscribers(listener);
    ...
}
  •  注册时会找到 listener 中所有带有 @Subscribe 的方法,并根据方法的参数类型进行分类
private Multimap, Subscriber> findAllSubscribers(Object listener) {
    Multimap, Subscriber> methodsInListener = HashMultimap.create();
    Class clazz = listener.getClass();
    Iterator i$ = getAnnotatedMethods(clazz).iterator();

    while(i$.hasNext()) {
        Method method = (Method)i$.next();
        Class[] parameterTypes = method.getParameterTypes();
        Class eventType = parameterTypes[0];
        methodsInListener.put(eventType, Subscriber.create(this.bus, listener, method));
    }

    return methodsInListener;
}
  • 判断方法是不是订阅者
private static ImmutableList getAnnotatedMethodsNotCached(Class clazz) {
    Set> supertypes = TypeToken.of(clazz).getTypes().rawTypes();
    Map identifiers = Maps.newHashMap();
    Iterator i$ = supertypes.iterator();

    while(i$.hasNext()) {
        Class supertype = (Class)i$.next();
        Method[] arr$ = supertype.getDeclaredMethods();
        int len$ = arr$.length;

        for(int i$ = 0; i$ < len$; ++i$) {
            Method method = arr$[i$];
            if (method.isAnnotationPresent(Subscribe.class) && !method.isSynthetic()) {
               ...
            }
        }
    }

    return ImmutableList.copyOf(identifiers.values());
}
  • 通知方法 , 获取参数为event类型的全部观察者
public void post(Object event) {
    Iterator eventSubscribers = this.subscribers.getSubscribers(event);
    if (eventSubscribers.hasNext()) {
        this.dispatcher.dispatch(event, eventSubscribers);
    } else if (!(event instanceof DeadEvent)) {
        this.post(new DeadEvent(this, event));
    }
}
  • 将通知分发给观察者们
void dispatch(Object event, Iterator subscribers) {
    Preconditions.checkNotNull(event);
    Preconditions.checkNotNull(subscribers);
    Queue queueForThread = (Queue)this.queue.get();
    queueForThread.offer(new Dispatcher.PerThreadQueuedDispatcher.Event(event, subscribers));
    if (!((Boolean)this.dispatching.get()).booleanValue()) {
        this.dispatching.set(true);
        
        Dispatcher.PerThreadQueuedDispatcher.Event nextEvent;
        try {
            while((nextEvent = 	                           (Dispatcher.PerThreadQueuedDispatcher.Event)queueForThread.poll()) != null) {    
                while(nextEvent.subscribers.hasNext()) {
                    ((Subscriber)nextEvent.subscribers.next()).dispatchEvent(nextEvent.event);
                }
            }
        } finally {
            this.dispatching.remove();
            this.queue.remove();
        }
    }

}
  • 具体的执行带有 @Subscribe 的方法,异步执行,提高效率
final void dispatchEvent(final Object event) {
    this.executor.execute(new Runnable() {
        public void run() {
            try {
                Subscriber.this.invokeSubscriberMethod(event);
            } catch (InvocationTargetException var2) {
                Subscriber.this.bus.handleSubscriberException(var2.getCause(), 			                            Subscriber.this.context(event));
            }

        }
    });
}

 

你可能感兴趣的:(Guava)