zoukankan      html  css  js  c++  java
  • EventBus 源码学习

    打开一看,原来相关代码并不多,下面看下细节

    主要方法也就是注册,取消注册和发送事件,可以看到两个主要的变量就是subscribers和dispatcher

      public void register(Object object) {
        subscribers.register(object);
      }

    首先看下注册类中做了什么,在下面的注册类中,可以看到首先调用了这个方法,对传入的listener类型,利用反射拿到信息

      /**
       * Returns all subscribers for the given listener grouped by the type of event they subscribe to.
       */
      private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) {
        Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create();
        Class<?> clazz = listener.getClass();
        for (Method method : getAnnotatedMethods(clazz)) {
          Class<?>[] parameterTypes = method.getParameterTypes();
          Class<?> eventType = parameterTypes[0];
          methodsInListener.put(eventType, Subscriber.create(bus, listener, method));
        }
        return methodsInListener;
      }

    debug下就清楚了

      /** Registers all subscriber methods on the given listener object. */
      void register(Object listener) {
        Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);
    
        for (Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {
          Class<?> eventType = entry.getKey();
          Collection<Subscriber> eventMethodsInListener = entry.getValue();
    
          CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);
    
          if (eventSubscribers == null) {
            CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<>();
            eventSubscribers =
                MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);
          }
    
          eventSubscribers.addAll(eventMethodsInListener);
        }
      }

     

    注册后这里的订阅者会保存如下信息。

    其次是分发

      public void post(Object event) {
        Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);
        if (eventSubscribers.hasNext()) {
          dispatcher.dispatch(event, eventSubscribers);
        } else if (!(event instanceof DeadEvent)) {
          // the event had no subscribers and was not itself a DeadEvent
          post(new DeadEvent(this, event));
        }
      }

    可见是先拿注册信息,再分发

        @Override
        void dispatch(Object event, Iterator<Subscriber> subscribers) {
          checkNotNull(event);
          checkNotNull(subscribers);
          Queue<Event> queueForThread = queue.get();
          queueForThread.offer(new Event(event, subscribers));
    
          if (!dispatching.get()) {
            dispatching.set(true);
            try {
              Event nextEvent;
              while ((nextEvent = queueForThread.poll()) != null) {
                while (nextEvent.subscribers.hasNext()) {
                  nextEvent.subscribers.next().dispatchEvent(nextEvent.event);
                }
              }
            } finally {
              dispatching.remove();
              queue.remove();
            }
          }
        }

     这里的dispatch通过反射执行

      /** Dispatches {@code event} to this subscriber using the proper executor. */
      final void dispatchEvent(final Object event) {
        executor.execute(
            new Runnable() {
              @Override
              public void run() {
                try {
                  invokeSubscriberMethod(event);
                } catch (InvocationTargetException e) {
                  bus.handleSubscriberException(e.getCause(), context(event));
                }
              }
            });
      }

    再下级

      /**
       * Invokes the subscriber method. This method can be overridden to make the invocation
       * synchronized.
       */
      @VisibleForTesting
      void invokeSubscriberMethod(Object event) throws InvocationTargetException {
        try {
          method.invoke(target, checkNotNull(event));
        } catch (IllegalArgumentException e) {
          throw new Error("Method rejected target/argument: " + event, e);
        } catch (IllegalAccessException e) {
          throw new Error("Method became inaccessible: " + event, e);
        } catch (InvocationTargetException e) {
          if (e.getCause() instanceof Error) {
            throw (Error) e.getCause();
          }
          throw e;
        }
      }

    至此结束调用,这种设计还蛮特别的,值得学习

  • 相关阅读:
    编程题:数组中出现超数组长度一半的数字
    编程题:两数之和&数组中相加为0的三元数组
    编程题:最小矩阵路径
    编程题:斐波那契数列青蛙跳台阶
    向excel文件中写内容
    Java:使用jxl读取excel文件内容
    索尼1a dac插电脑用什么驱动。在哪下载,求助
    idea启动项目报端口号冲突或被占用
    两分钟解决IntelliJ IDEA中文乱码问题
    IntelliJ IDEA以不同格式导出数据库的数据
  • 原文地址:https://www.cnblogs.com/it-worker365/p/9945566.html
Copyright © 2011-2022 走看看