List subscriberMethods = subscriberMethodFinder.findSubscriberMethods(subscriberClass);
synchronized (this) {
for (SubscriberMethod subscriberMethod : subscriberMethods) {
// subsciber 对 List 中每个 SubscriberMethod 进行订阅
subscribe(subscriber, subscriberMethod);
}
}
}
获取当前注册对象所有订阅方法信息
先查看如何根据当前注册类获取 List 的,SubscriberMethodFinder#findSubscriberMethods(Class<?> subscriberClass)
源码精简如下:
List findSubscriberMethods(Class<?> subscriberClass) {
List subscriberMethods = METHOD_CACHE.get(subscriberClass);
// 如果已存在则返回
if (subscriberMethods != null) {
return subscriberMethods;
}
subscriberMethods = findUsingReflection(subscriberClass);
METHOD_CACHE.put(subscriberClass, subscriberMethods);
return subscriberMethods;
}
METHOD_CACHE
前面提到过,是存着注册类与其所有需要回调的 Event 方法列表的键值对。如果已经存在则直接返回,如果否则需要通过 findUsingReflection(subscriberClass)
方法进行查找再返回,当然,返回之前需要存入 METHOD_CACHE
中,否则该 METHOD_CACHE
就没有存在的意义了。
SubscriberMethodFinder#findUsingReflection()
源码如下:
private List findUsingReflection(Class<?> subscriberClass) {
FindState findState = prepareFindState();
findState.initForSubscriber(subscriberClass);
while (findState.clazz != null) {
// 通过纯反射去获取被 @Subscribe 所修饰的方法
findUsingReflectionInSingleClass(findState);
// 将当前 class 的父类 class 赋值给 findState.clazz
findState.moveToSuperclass();
}
// 重置 FindState 便于下一次回收利用
return getMethodsAndRelease(findState);
}
初始化 FindState 对象后,会进入一个 while 循环中,不停地去反射获取当前类和其父类(注意,在 Java 中,如果当前类实现了一个接口,即使该接口的方法被 @Subscribe
所修饰,当前类中的方法也是不包含该注解属性的,所以如果在接口中对某个方法使用了 @Subscribe
修饰然后让类去实现这个接口是没有任何作用的)的订阅方法并添入列表中,最终返回这个列表并重置 FindState 对象利于下一次重复使用。反射获取当前类和其父类的订阅方法源码简化如下:
private void findUsingReflectionInSingleClass(FindState findState) {
Method[] methods;
try {
// 返回当前类自身方法和显式重载的父类方法
methods = findState.clazz.getDeclaredMethods();
} catch (Throwable th) {
methods = findState.clazz.getMethods();
findState.skipSuperClasses = true;
}
for (Method method : methods) {
int modifiers = method.getModifiers();
if ((modifiers & Modifier.PUBLIC) != 0 && (modifiers & MODIFIERS_IGNORE) == 0) {
Class<?>[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { Subscribe subscribeAnnotation = method.getAnnotation(Subscribe.class); if (subscribeAnnotation != null) { Class<?> eventType = parameterTypes[0];
// needCheck
if (f