首發於Enaium的我的博客java
EventBus,什麼是EventBus。git
EventBus是事件發佈-訂閱總線,簡單來講監聽一個事件,一個方法訂閱這個事件,若是事件調用,那麼訂閱了這個事件的方法也會跟着調用,這就是EventBus。github
建立一個註解,用於訂閱事件,名字能夠隨便起,固然也能夠叫Subscribe,我這裏叫Event。安全
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Event { }
建立Listener監聽器。測試
public class Listener { }
建立MethodBean類,來儲存訂閱方法,Object是訂閱類的對象,Method就是被訂閱的方法。this
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。code
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) { } }
註冊。blog
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"); } } }