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