//添加订阅的逻辑的具体实现,整个register()到此结束
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
//根据订阅的某一个具体method获取其相应对应的event事件类class
Class> eventType = subscriberMethod.eventType;
//订阅者,订阅方法封装起来
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
//根据event从Map中获取所有订阅这个event的subscribe的list列表
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
//这个event从来没有被任何subscrobe订阅过,这个Subscribe之前没有注册过这个事件,此时eventType--subscriptions关联一下
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
//所有订阅该event的subscribe中,已经存在改subscribe,说明这个subscribe老爸订阅过了(不允许)
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
//根据优先级决定这个subscribe在订阅此event的所有subscribe的队列中的位置
int size = subscriptions.size();
for (int i = 0; i <= size; i++) {
if (i == size || subscriberMethod.priority > subscriptions.get(i).subscriberMethod.priority) {
subscriptions.add(i, newSubscription);
break;
}
}
//根据subscribe获取这个它当前所有订阅的event集合
List> subscribedEvents = typesBySubscriber.get(subscriber);
//说明此subscribe没有订阅过这个event,此时subscriber--subscribedEvents关联下
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
//粘性事件
if (subscriberMethod.sticky) {
if (eventInheritance) {
Set, Object>> entries = stickyEvents.entrySet();
for (Map.Entry, Object> entry : entries) {
Class> candidateEventType = entry.getKey();
if (eventType.isAssignableFrom(candidateEventType)) {
Object stickyEvent = entry.getValue();
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
} else {
Object stickyEvent = stickyEvents.get(eventType);
checkPostStickyEventToSubscription(newSubscription, stickyEvent);
}
}
}
SubscriberMethodFinder#findSubscriberMethods
//根据订阅者查找当前订阅者所有订阅的方法
List findSubscriberMethods(Class> subscriberClass) {
//METHOD_CACHE是一个Map, List>,在SubscriberMethodFinder 39行,根据订阅者查出它所有订阅的方法或者event
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
if (subscriberMethods != null) {
return subscriberMethods;
}
if (ignoreGeneratedIndex) {
subscriberMethods = findUsingReflection(subscriberClass);
} else {
subscriberMethods = findUsingInfo(subscriberClass);
}
//当没有@Subscribe这样的public方法时候抛异常
if (subscriberMethods.isEmpty()) {
throw new EventBusException("Subscriber " + subscriberClass
+ " and its super classes have no public methods with the @Subscribe annotation");
} else {//第一次都会走到这
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
}
//允许一个类有多个参数相同的订阅方法。
boolean checkAdd(Method method, Class> eventType) {
// 2 level check: 1st level with event type only (fast), 2nd level with complete signature when required.
// Usually a subscriber doesn't have methods listening to the same event type.
Object existing = anyMethodByEventType.put(eventType, method);
if (existing == null) {
return true;
} else {
if (existing instanceof Method) {
if (!checkAddWithMethodSignature((Method) existing, eventType)) {
// Paranoia check
throw new IllegalStateException();
}
// Put any non-Method object to "consume" the existing Method
anyMethodByEventType.put(eventType, this);
}
return checkAddWithMethodSignature(method, eventType);
}
}
//子类继承并重写了父类的订阅方法,那么只会把子类的订阅方法添加到订阅者列表,父类的方法会忽略。
private boolean checkAddWithMethodSignature(Method method, Class> eventType) {
methodKeyBuilder.setLength(0);
methodKeyBuilder.append(method.getName());
methodKeyBuilder.append('>').append(eventType.getName());
String methodKey = methodKeyBuilder.toString();
Class> methodClass = method.getDeclaringClass();
Class> methodClassOld = subscriberClassByMethodKey.put(methodKey, methodClass);
if (methodClassOld == null || methodClassOld.isAssignableFrom(methodClass)) {
// Only add if not already found in a sub class
return true;
} else {
// Revert the put, old class is further down the class hierarchy
subscriberClassByMethodKey.put(methodKey, methodClassOld);
return false;
}
}
SubscriberMethodFinder#getMethodsAndRelease
//把当前订阅者所有的订阅方法的List返回到最初register()地方,findUseringInfo()到此终结!,整个register也基本结束
private List getMethodsAndRelease(FindState findState) {
List subscriberMethods = new ArrayList<>(findState.subscriberMethods);
findState.recycle();
synchronized (FIND_STATE_POOL) {
for (int i = 0; i < POOL_SIZE; i++) {
if (FIND_STATE_POOL[i] == null) {
FIND_STATE_POOL[i] = findState;
break;
}
}
}
return subscriberMethods;
}
取消注册源码分析:
取消注册其实就是操作相关map做remove操作:
EventBus#unregister
//操作Map
EventBus#unsubscribeByEventType
//操作event---subscribe这个map将这个subscribe中的所有event对应的这个subscribe移除掉
private void unsubscribeByEventType(Object subscriber, Class> eventType) {
List subscriptions = subscriptionsByEventType.get(eventType);
if (subscriptions != null) {
int size = subscriptions.size();
for (int i = 0; i < size; i++) {
Subscription subscription = subscriptions.get(i);
if (subscription.subscriber == subscriber) {
subscription.active = false;
subscriptions.remove(i);
i--;
size--;
}
}
}
}
2,开始真正的表演:post触发事件传递源码分析
这里盗用别人图借用一下!!!
首先看一个event发送过程中状态的封装类:封装订阅者,订阅的event,线程信息
EventBus#PostingThreadState
final static class PostingThreadState {
final List
EventBus#post
public void post(Object event) {
//currentPostingThreadState是一个ThreadLocal,而ThreadLocal是每个线程独享的,其数据别的线程是不能访问的,可以理解为一个线程自己独有一个线程本地变量
PostingThreadState postingState = currentPostingThreadState.get();
//获取当前线程的事件队列
List eventQueue = postingState.eventQueue;
eventQueue.add(event);
if (!postingState.isPosting) {
postingState.isMainThread = Looper.getMainLooper() == Looper.myLooper();
postingState.isPosting = true;
if (postingState.canceled) {
throw new EventBusException("Internal error. Abort state was not reset");
}
try {
while (!eventQueue.isEmpty()) {
postSingleEvent(eventQueue.remove(0), postingState);
}
} finally {
postingState.isPosting = false;
postingState.isMainThread = false;
}
}
}
EventBus#postSingleEvent
private void postSingleEvent(Object event, PostingThreadState postingState) throws Error {
Class> eventClass = event.getClass();
boolean subscriptionFound = false;
if (eventInheritance) {
List> eventTypes = lookupAllEventTypes(eventClass);
int countTypes = eventTypes.size();
for (int h = 0; h < countTypes; h++) {
Class> clazz = eventTypes.get(h);
subscriptionFound |= postSingleEventForEventType(event, postingState, clazz);
}
} else {
subscriptionFound = postSingleEventForEventType(event, postingState, eventClass);
}
if (!subscriptionFound) {
if (logNoSubscriberMessages) {
Log.d(TAG, "No subscribers registered for event " + eventClass);
}
if (sendNoSubscriberEvent && eventClass != NoSubscriberEvent.class &&
eventClass != SubscriberExceptionEvent.class) {
post(new NoSubscriberEvent(this, event));
}
}
}
什么是Hessian
The Hessian binary web service protocol makes web services usable without requiring a large framework, and without learning yet another alphabet soup of protocols. Because it is a binary p
在Spark Shell上,通过创建HiveContext可以直接进行Hive操作
1. 操作Hive中已存在的表
[hadoop@hadoop bin]$ ./spark-shell
Spark assembly has been built with Hive, including Datanucleus jars on classpath
Welcom
JMS Message Delivery Reliability and Acknowledgement Patterns
http://wso2.com/library/articles/2013/01/jms-message-delivery-reliability-acknowledgement-patterns/
Transaction and redelivery in
转载请出自出处:http://eksliang.iteye.com/blog/2177567 一、游标
数据库使用游标返回find的执行结果。客户端对游标的实现通常能够对最终结果进行有效控制,从shell中定义一个游标非常简单,就是将查询结果分配给一个变量(用var声明的变量就是局部变量),便创建了一个游标,如下所示:
> var