自写一个EventBus

简介: entBus,什么是EventBus。EventBus是事件发布-订阅总线,简单来说监听一个事件,一个方法订阅这个事件,如果事件调用,那么订阅了这个事件的方法也会跟着调用,这就是EventBus。

首发于Enaium的个人博客


EventBus,什么是EventBus。

EventBus是事件发布-订阅总线,简单来说监听一个事件,一个方法订阅这个事件,如果事件调用,那么订阅了这个事件的方法也会跟着调用,这就是EventBus。

创建一个注解,用于订阅事件,名字可以随便起,当然也可以叫Subscribe,我这里叫Event。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Event {
   
}

创建Listener监听器。

public class Listener {
   
}

创建MethodBean类,来储存订阅方法,Object是订阅类的对象,Method就是被订阅的方法。

public class MethodBean {
   
    private final Object object;
    private final Method method;

    public MethodBean(Object object, Method method) {
   
        this.object = object;
        this.method = method;
    }

    public Object getObject() {
   
        return object;
    }

    public Method getMethod() {
   
        return method;
    }
}

创建一个EventManager,来管理订阅的事件。

public class EventManager {
   
}

创建一个HashMap合集K是监听器,V是被调用的方法,因为一个监听器可能有多个方法,并且要保证线程安全,需要使用CopyOnWriteArrayList。

public class EventManager {
   
    private final HashMap<Class<? extends Listener>, CopyOnWriteArrayList<MethodBean>> events = new HashMap<>();
}

创建register和unregister方法来注册和取消注册订阅的对象。

public class EventManager {
   
    public void register(Object o) {
   

    }

    public void unregister(Object o) {
   

    }
}

注册。

public void register(Object o) {
   
     Class<?> type = o.getClass();//获取类。

    for (Method method : type.getDeclaredMethods()) {
   //遍历出所有方法。
        if (method.getParameterTypes().length == 1 && method.isAnnotationPresent(Event.class)) {
   //保证方法只有一个参数,并且有Event这个注解。
            method.setAccessible(true);
            @SuppressWarnings("unchecked")
            Class<? extends Listener> listener = (Class<? extends Listener>) method.getParameterTypes()[0];

            MethodBean methodBean = new MethodBean(o, method);

            //把这些都put到events里面。
            if (events.containsKey(listener)) {
   
                if (!events.get(listener).contains(methodBean)) {
   
                    events.get(listener).add(methodBean);
                }
            } else {
   
                events.put(listener, new CopyOnWriteArrayList<>(Collections.singletonList(methodBean)));
            }
        }
    }
}

取消注册很简单,只要将events的K和V移除就行。

public void unregister(Object o) {
   
    events.values().forEach(methodBeans -> methodBeans.removeIf(methodMethodBean -> methodMethodBean.getObject().equals(o)));
    events.entrySet().removeIf(event -> event.getValue().isEmpty());
}

创建一个getEvent方法来获取一个监听器的所有订阅。

public CopyOnWriteArrayList<MethodBean> getEvent(Class<? extends Listener> type) {
   
    return events.get(type);
}

创建一个单例。

public enum Main {
   

    INSTANCE;

    EventManager eventManager = new EventManager();

}

回到刚才创建的Listener类。

创建一个call方法来进行事件触发操作,当事件触发,获取监听器的所有订阅方法来调用,参数就是当前的监听器。

public class Listener {
   
    public void call() {
   
        CopyOnWriteArrayList<MethodBean> methodBeans = Main.INSTANCE.eventManager.getEvent(this.getClass());

        if(methodBeans == null) {
   
            return;
        }

        methodBeans.forEach(event -> {
   
            try {
   
                event.getMethod().invoke(event.getObject(), this);
            } catch (IllegalAccessException | InvocationTargetException e) {
   
                e.printStackTrace();
            }
        });
    }
}

创建一个监听器。

public class UpdateEvent extends Listener {
   
}

一个简单的EventBus已经写好了,现在来测试一下。

public enum Main {
   

    INSTANCE;

    EventManager eventManager = new EventManager();

    public static void main(String[] args) {
   
        Main.INSTANCE.eventManager.register(new Test());//register
        new UpdateEvent().call();
    }

    static class Test {
   
        @Event
        public void on(UpdateEvent e) {
   
            System.out.println("Event trigger");
        }
    }
}

源码

目录
相关文章
|
JavaScript
手写代码:实现一个EventBus
EventBus,事件总线。总线一词来自于《计算机组成原理》中的”系统总线“,是指用于连接多个部件的信息传输线,各部件共享的传输介质。我们通常把事件总线也成为自定义事件,一般包含`on`、`once`、`emit`、`off`等方法。在Vue2中想要实现EventBus比较简单,直接暴露出一个`new Vue()`实例即可,以此为思路,我们应该如何自定义实现EventBus呢?
486 0
手写代码:实现一个EventBus
DHL
|
Java API Android开发
EventBus3.1用法详解
EventBus是Android和Java的发布/订阅事件总线。从EventBus3.1开始支持普通Java(非android)项目。GitHub的地址
DHL
240 0
EventBus3.1用法详解
|
监控 Java
说下你可能没用过的EventBus
一般情况下,我们会做成异步的方式,使用MQ自己发送自己消费,或者说一个线程池搞定,这样的话不影响主业务逻辑,可以提高性能,并且代码做到了解耦。
|
存储 缓存 调度
EventBus源码解析
EventBus源码解析
736 0
EventBus源码解析
EventBus简单使用
EventBus简单使用
175 0
|
消息中间件 Android开发
【EventBus】发布-订阅模式 ( EventBus 组成模块 | 观察者模式 )
【EventBus】发布-订阅模式 ( EventBus 组成模块 | 观察者模式 )
339 0
【EventBus】发布-订阅模式 ( EventBus 组成模块 | 观察者模式 )
|
缓存
【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )
【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )
127 0
【EventBus】EventBus 源码解析 ( 注册订阅者总结 | EventBus 注册订阅者流程梳理 )
EventBus实现组件间异步
最近新换了工作,刚来比较轻松,所以想自己写几个小工具提升下自己的效率。在开发过程中发现组件的一些通讯问题,如果采用异步的方式,效率能得到很大提升,所以决定使用到EventBus(消息总线)技术,达到异步事件处理的目的。
【EventBus】EventBus 源码解析 ( 事件发送 | postToSubscription 方法 | EventBus 线程模式处理细节 )
【EventBus】EventBus 源码解析 ( 事件发送 | postToSubscription 方法 | EventBus 线程模式处理细节 )
127 0
|
存储
【EventBus】EventBus 源码解析 ( 注册订阅者总结 | 从封装的数据结构角度分析 EventBus )
【EventBus】EventBus 源码解析 ( 注册订阅者总结 | 从封装的数据结构角度分析 EventBus )
125 0