骨头版的EventBus

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author ShineZeng
 * @Date 2014-05-11
 */
public class SimpleEventBus {

	public static final String BUS_Event_PATTERN = "onBusEvent";
	public static final String BUS_TOPIC_PATTERN = "onBusTopic";

	static interface Topic {
	};

	private HashMap<Class<?>, LinkedList<Subscriber>> subscribersByType;
	private HashMap<String, LinkedList<Subscriber>> subscribersByTopic;
	private ReentrantReadWriteLock subscribersByTypeLock;

	public SimpleEventBus() {
		/** 天啊 */
		subscribersByType = new HashMap<Class<?>, LinkedList<Subscriber>>();
		subscribersByTopic = new HashMap<String, LinkedList<Subscriber>>();
		subscribersByTypeLock = new ReentrantReadWriteLock();
	}

	public void register(Object subObj) {
		Map<Class<?>, Subscriber> methodsInListener = findAllSubscribers(subObj);
		Map<String, Subscriber> topicMethodsInListener = findAllTopicSubscribers(subObj);
		subscribersByTypeLock.writeLock().lock();
		try {
			for (Entry<Class<?>, Subscriber> entry : methodsInListener
					.entrySet()) {
				LinkedList<Subscriber> list = subscribersByType.get(entry
						.getKey());
				if (list == null) {
					list = new LinkedList<SimpleEventBus.Subscriber>();
					subscribersByType.put(entry.getKey(), list);
				}
				list.add(entry.getValue());
			}
			for (Entry<String, Subscriber> entry : topicMethodsInListener
					.entrySet()) {
				LinkedList<Subscriber> list = subscribersByTopic.get(entry
						.getKey());
				if (list == null) {
					list = new LinkedList<SimpleEventBus.Subscriber>();
					subscribersByTopic.put(entry.getKey(), list);
				}
				list.add(entry.getValue());
			}
		} finally {
			subscribersByTypeLock.writeLock().unlock();
		}
	}

	public void unregister(Object subObj) {
		Map<Class<?>, Subscriber> methodsInListener = findAllSubscribers(subObj);
		Map<String, Subscriber> topicMethodsInListener = findAllTopicSubscribers(subObj);
		subscribersByTypeLock.writeLock().lock();
		try {
			for (Entry<Class<?>, Subscriber> entry : methodsInListener
					.entrySet()) {
				LinkedList<Subscriber> list = subscribersByType.get(entry
						.getKey());
				if (list != null) {
					list.remove(entry.getValue());
					if (list.isEmpty()) {
						subscribersByType.remove(entry.getKey());
					}
				}
			}
			for (Entry<String, Subscriber> entry : topicMethodsInListener
					.entrySet()) {
				LinkedList<Subscriber> list = subscribersByTopic.get(entry
						.getKey());
				if (list != null) {
					list.remove(entry.getValue());
					if (list.isEmpty()) {
						subscribersByTopic.remove(entry.getKey());
					}
				}
			}
		} finally {
			subscribersByTypeLock.writeLock().unlock();
		}
	}

	public void post(Object evt) {
		subscribersByTypeLock.readLock().lock();
		LinkedList<Subscriber> subscriberLists = subscribersByType.get(evt
				.getClass());
		if (subscriberLists != null && !subscriberLists.isEmpty()) {
			for (Subscriber subscriber : subscriberLists) {
				try {
					subscriber.fireEvent(evt);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} else {
			subscriberLists = subscribersByType.get(DeadEvent.class);
			if (subscriberLists != null && !subscriberLists.isEmpty()) {
				post(new DeadEvent(evt));
			}
		}
		subscribersByTypeLock.readLock().unlock();
	}

	public void postTopic(String topic, Object evt) {
		subscribersByTypeLock.readLock().lock();
		LinkedList<Subscriber> subscriberLists = subscribersByTopic.get(topic);
		if (subscriberLists != null && !subscriberLists.isEmpty()) {
			for (Subscriber subscriber : subscriberLists) {
				try {
					subscriber.fireEvent(evt);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		} else {
			subscriberLists = subscribersByType.get(DeadEvent.class);
			if (subscriberLists != null && !subscriberLists.isEmpty()) {
				post(new DeadEvent(topic, evt));
			}
		}
		subscribersByTypeLock.readLock().unlock();
	}

	protected Map<Class<?>, Subscriber> findAllSubscribers(Object o) {
		Map<Class<?>, Subscriber> result = new HashMap<Class<?>, Subscriber>();
		Method[] methods = o.getClass().getMethods();
		for (Method method : methods) {
			if (method.getName().contains(BUS_Event_PATTERN)
					&& method.getParameterTypes().length == 1) {
				result.put(method.getParameterTypes()[0], new Subscriber(o,
						method));
			}
		}
		return result;
	}

	protected Map<String, Subscriber> findAllTopicSubscribers(Object o) {
		Map<String, Subscriber> result = new HashMap<String, Subscriber>();
		Method[] methods = o.getClass().getMethods();
		for (Method method : methods) {
			if (method.getName().contains(BUS_TOPIC_PATTERN)
					&& method.getParameterTypes().length == 1) {
				result.put(
						method.getName().substring(BUS_TOPIC_PATTERN.length()),
						new Subscriber(o, method));
			}
		}
		return result;
	}

	protected static class Subscriber {
		Object subSource;
		Method subMethod;

		public Subscriber(Object subSource, Method subMethod) {
			this(subSource, subMethod, null);
		}

		public Subscriber(Object subSource, Method subMethod, String topic) {
			this.subSource = subSource;
			this.subMethod = subMethod;
		}

		public void fireEvent(Object event) throws IllegalArgumentException,
				IllegalAccessException, InvocationTargetException {
			subMethod.invoke(subSource, event);
		}

		@Override
		public boolean equals(Object obj) {
			boolean result = false;
			if (obj instanceof Subscriber) {
				Subscriber sub = (Subscriber) obj;
				result = this.subSource == sub.subSource
						&& this.subMethod.equals(sub.subMethod);
			}
			return result;
		}
	}

	public static class DeadEvent {
		Object sourceEvent;
		String topic;

		public DeadEvent(Object sourceEvent) {
			this(null, sourceEvent);
		}

		public DeadEvent(String topic, Object sourceEvent) {
			this.sourceEvent = sourceEvent;
			this.topic = topic;
		}

		public Object getSourceEvent() {
			return sourceEvent;
		}

		public String getTopic() {
			return topic;
		}
	}

	public static void main(String[] args) {
		class TestListenerA {
			public void onBusEventLong(Long lon) {
				System.out.println("A onEventLong:" + lon);
			}

			public void onBusEventDead(DeadEvent evt) {
				System.out.println("A onEventDead:" + evt.getSourceEvent());
			}

			public void onBusTopicCode(String code) {
				System.out.println("fire code: " + code);
			}
		}
		class TestListenerB {
			public void onBusEventString(String str) {
				System.out.println("B onEventStr:" + str);
			}

			public void onBusEventDead(DeadEvent evt) {
				System.out.println("B onEventDead:" + evt.getSourceEvent());
			}
		}
		SimpleEventBus bus = new SimpleEventBus();
		TestListenerA A = new TestListenerA();
		TestListenerB B = new TestListenerB();

		System.out.println("----------------------Post before register");
		bus.post(new Long(2008));
		bus.post(new Double(2009));
		bus.post(new String("string"));
		bus.postTopic("Code", "HSI.FHSI1");

		bus.register(A);
		System.out.println("----------------------Post after register A");
		bus.post(new Long(2008));
		bus.post(new Double(2009));
		bus.post(new String("string"));
		bus.postTopic("Code", "HSI.FHSI1");

		bus.register(B);
		System.out.println("----------------------Post after register B");
		bus.post(new Long(2008));
		bus.post(new Double(2009));
		bus.post(new String("string"));
		bus.postTopic("Code", "HSI.FHSI1");

		bus.unregister(A);
		System.out.println("----------------------Post after unregister A");
		bus.post(new Long(2008));
		bus.post(new Double(2009));
		bus.post(new String("string"));
		bus.postTopic("Code", "HSI.FHSI1");

		bus.unregister(B);
		System.out.println("----------------------Post after unregister B");
		bus.post(new Long(2008));
		bus.post(new Double(2009));
		bus.post(new String("string"));
		bus.postTopic("Code", "HSI.FHSI1");
	}
}


转载于:https://my.oschina.net/u/759974/blog/263451

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值