美文网首页java
Guava eventBus 关于@AllowConcurren

Guava eventBus 关于@AllowConcurren

作者: guli_2018 | 来源:发表于2017-10-26 16:42 被阅读204次

    背景

    以下带有@Subscribe的方法简称订阅方法。
    @AllowConcurrentEvents的作用就是当使用多线程模式的时候,标记订阅的方法是线程安全的。使之EventBus可以针对同个subscribe方法进行多线程。简单链接:http://www.cnblogs.com/whitewolf/p/4132840.html

    经历

    但当@Subscribe方法存在继承逻辑时,坑就出现了。荔枝:

    package eh;
    
    import com.google.common.eventbus.AllowConcurrentEvents;
    import com.google.common.eventbus.EventBus;
    import com.google.common.eventbus.Subscribe;
    
    /**
     * Created by shenhj on 2017/10/26.
     */
    public class EventBusTest {
    
        public static void main(String[] args) {
            EventBus eventBus = new EventBus();
            eventBus.register(new EventListener1());
            eventBus.post(1);
            eventBus.post(1L);
            eventBus.post("hello");
        }
        public static class EventListener1 implements EventListener{
            public void listenInteger(Integer i) {//此方法不会被加入eventBus的loadingCache,父类方法取代之
                System.out.println(i);
            }
            @Subscribe
            public void listenLong(Long l) {//此方法取代父类方法加入eventBus的loadingCache
                System.out.println(l);
            }
            @Subscribe
            @AllowConcurrentEvents
            public void listenString(String string) {//此方法取代父类方法加入eventBus的loadingCache
                System.out.println(string);
            }
        }
        public  interface EventListener {
            @Subscribe
            @AllowConcurrentEvents
            void listenInteger(Integer i);
    
            @Subscribe
            @AllowConcurrentEvents
            void listenLong(Long i);
    
            @Subscribe
            @AllowConcurrentEvents
            void listenString(String string);
        }
    }
    

    eventBus在register方法时会去加载带有@Subscribe的方法到loadingCache。又由于jvm的类加载机制,子类的方法会优先被遍历,导致带有@Subscribe的子类方法会取代父类方法加载到loadingCache,使父类方法上的@AllowConcurrentEvents注解无效。具体eventBus是怎么遍历,请看代码:

    private static ImmutableList<Method> getAnnotatedMethodsInternal(Class<?> clazz) {
        Set<? extends Class<?>> supers = TypeToken.of(clazz).getTypes().rawTypes();
        Map<MethodIdentifier, Method> identifiers = Maps.newHashMap();
        //向上遍历所有相关的注册类,
        // (class eh.EventBusTest$EventListener1)->(interface eh.EventBusTest$EventListener)->(class java.lang.Object)
        for (Class<?> superClazz : supers) {
          for (Method superClazzMethod : superClazz.getMethods()) {
            if (superClazzMethod.isAnnotationPresent(Subscribe.class)
                && !superClazzMethod.isBridge()) {//桥接方法适用与泛型方法的override
              Class<?>[] parameterTypes = superClazzMethod.getParameterTypes();
              if (parameterTypes.length != 1) {
                throw new IllegalArgumentException("Method " + superClazzMethod
                    + " has @Subscribe annotation, but requires " + parameterTypes.length
                    + " arguments.  Event subscriber methods must require a single argument.");
              }
    
              MethodIdentifier ident = new MethodIdentifier(superClazzMethod);
              if (!identifiers.containsKey(ident)) {//用方法名和参数类型做判断
                identifiers.put(ident, superClazzMethod);
              }
            }
          }
        }
        return ImmutableList.copyOf(identifiers.values());
      }
    

    推荐

    @AllowConcurrentEvents@Subscribe一同使用

    相关文章

      网友评论

        本文标题:Guava eventBus 关于@AllowConcurren

        本文链接:https://www.haomeiwen.com/subject/noskpxtx.html