public class SubscriberMethod {
final Method method; //方法,用于反射回调的
final ThreadMode threadMode; //指定的线程
final Class> eventType; //事件的类型,后续要通过这个找相关的监听方法
final int priority; //优先级
final boolean sticky; //是否接收粘性事件
}
找到所有监听的方法后,会通过subscribe方法进行关联,来看具体实现:
private void subscribe(Object subscriber, SubscriberMethod subscriberMethod) {
Class> eventType = subscriberMethod.eventType;
// Subscription是监听方法subscriberMethod和观察者subscriber绑定关系,用于后面反射调用方法的
Subscription newSubscription = new Subscription(subscriber, subscriberMethod);
// subscriptions是此监听方法中的事件类型对应的所有subscriptions,是以事件类型为key的
CopyOnWriteArrayList subscriptions = subscriptionsByEventType.get(eventType);
// 如果不存在则新建一个,再把新找到的SubscriberMethod添加进去,这样后面发送此事件类型时它才能被触发
if (subscriptions == null) {
subscriptions = new CopyOnWriteArrayList<>();
subscriptionsByEventType.put(eventType, subscriptions);
} else {
if (subscriptions.contains(newSubscription)) {
throw new EventBusException("Subscriber " + subscriber.getClass() + " already registered to event "
+ eventType);
}
}
// 这里是根据优先级调整位置
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;
}
}
// 这里是从另一个角度看了,获取观察者所有监听的事件类型,之前是根据事件类型找不同观察者的方法,这里是根据观察者类找它所有监听的事件类型,这是为了反注册时用的
List> subscribedEvents = typesBySubscriber.get(subscriber);
if (subscribedEvents == null) {
subscribedEvents = new ArrayList<>();
typesBySubscriber.put(subscriber, subscribedEvents);
}
subscribedEvents.add(eventType);
// 如果方法是支持粘性事件的,就会从粘性事件缓存里找到最近一次的事件,直接通过checkPostStickyEventToSubscription进行事件发送
if (subscriberMethod.sticky) {
if (eventInheritance) {
// Existing sticky events of all subclasses of eventType have to be considered.
// Note: Iterating over all events may be inefficient with lots of sticky events,
// thus data structure should be changed to allow a more efficient lookup
// (e.g. an additional map storing sub classes of super classes: Class -> List).
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);
}
}
}
总结下注册的逻辑:
找到观察者里所有的监听方法
循环把所有监听方法和事件类型的关系保存下来
如果支持粘性事件就找最近一次同类型事件进行发送
再来看下发送的源码实现;
先看下相关的类说明:
/** For ThreadLocal, much faster to set (and get multiple values). */
final static class PostingThreadState {
final List
public void post(Object event) {
// 获取PostingThreadState,把事件加到事件队列中
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;
}
}
}
public void postSticky(Object event) {
synchronized (stickyEvents) {
stickyEvents.put(event.getClass(), event);
}
// Should be posted after it is putted, in case the subscriber wants to remove immediately
post(event);
}
总结下发送的逻辑:
如果是粘性事件就把事件存起来
通过事件类型找到所有相关的监听方法
通过反射在指定的处理线程中调用监听方法
最后看下反注册的源码实现:
public synchronized void unregister(Object subscriber) {
// 根据观察者找到所有监听的事件类型
List> subscribedTypes = typesBySubscriber.get(subscriber);
if (subscribedTypes != null) {
// 把此观察者从事件类型对应的所有方法中移除
for (Class> eventType : subscribedTypes) {
unsubscribeByEventType(subscriber, eventType);
}
typesBySubscriber.remove(subscriber);
} else {
Log.w(TAG, "Subscriber to unregister was not registered before: " + subscriber.getClass());
}
}
Traits are a fundamental unit of code reuse in Scala. A trait encapsulates method and field definitions, which can then be reused by mixing them into classes. Unlike class inheritance, in which each c
版本:WebLogic Server 10.3
说明:%DOMAIN_HOME%:指WebLogic Server 域(Domain)目录
例如我的做测试的域的根目录 DOMAIN_HOME=D:/Weblogic/Middleware/user_projects/domains/base_domain
1.为了保证操作安全,备份%DOMAIN_HOME%/security/Defa
http://crazyjvm.iteye.com/blog/1693757 文中提到相关超时问题,但是又出现了一个问题,我把min和max都设置成了180000,但是仍然出现了以下的异常信息:
Client session timed out, have not heard from server in 154339ms for sessionid 0x13a3f7732340003
在Mysql 众多表中查找一个表名或者字段名的 SQL 语句:
方法一:SELECT table_name, column_name from information_schema.columns WHERE column_name LIKE 'Name';
方法二:SELECT column_name from information_schema.colum