* * 订阅服务器具有必须由{@link Subscribe}注释的事件处理方法。...* {@link Subscribe}注释还允许类似{@link ThreadMode}和优先级的配置。...* 事件处理方法必须由{@link Subscribe}注释,必须是公共的,不返回任何内容(void), * 并且只有一个参数(事件)。...// 该 HashMap 的用途是保存当前的 eventType 对应的所有的订阅类和订阅方法 // 以便消息中心获取对应类型的消息后 , 可以顺利将其传递给相应订阅方法...// 注意:迭代所有事件可能效率低下,因为有很多粘性事件, // 因此,应更改数据结构以允许更高效的查找 // 例如,存储超类子类的附加映射
* 事件处理方法必须由{@link Subscribe}注释,必须是公共的,不返回任何内容(void), * 并且只有一个参数(事件)。...* * 订阅服务器具有必须由{@link Subscribe}注释的事件处理方法。...* {@link Subscribe}注释还允许类似{@link ThreadMode}和优先级的配置。...(subscriber, subscriberMethod); } } } } 二、订阅方法 ---- SubscriberMethod 对订阅的方法进行了一些封装...findUsingReflectionInSingleClass ---- 通过反射获取订阅者类中的所有方法 , 遍历 订阅者 类中的所有方法 , 过滤掉不符合条件的方法 , 将符合条件的方法封装到
本文源码基于: JDK13 Flow 官方注释翻译 一些接口和静态方法,为了建立流式组件, Publisher生成元素,被一个或者多个Subscriber消费,每一个Subscriber被Subscription...示例: 一个Flow.Publisher通常定义了他自己的Subscription实现,在subscribe方法中创建一个,然后叫他交给Flow.Subscriber。...这个类还可以作为生成项的子类的一个基础,并使用这个类中的方法来发布他们。 比如: 这里有一个周期性发布发布元素的类....(实际上,您可以添加方法来独立的启动和停止,在发布者之间共享线程池等等,或者使用SubmissionPublisher作为一个组件而不是超类.)...它使用单步请求他的发布者, 适应性更强的版本可以使用提交返回的延迟及其他方法来监控流.
那么我们来列举几个常用的属性加以讲解: //默认地,EventBus会考虑事件的超类,即事件如果继承自超类,那么该超类也会作为事件发送给订阅者。...,均有注释 //......,那么这个类必须有一个订阅方法,以@Subscribe注解标记的方法,接着调用register()方法来进行注册。...从FindState#checkAdd深入的一系列方法的作用: - 允许一个类有多个参数相同的订阅方法 - 子类继承并重写了父类的订阅方法,那么只会把子类的订阅方法添加到订阅者列表,父类的方法会忽略...,把subscriberMethods不断逐层返回,直到返回EventBus#register()方法,最后开始遍历每一个订阅方法,并调用subscribe(subscriber, subscriberMethod
> subscriberClass = subscriber.getClass(); // 就是当前的Activity中寻找到带有@Subscribe注解的方法集合 List...,其实还是一个很简单的逻辑,我们在代码中加入了一个标志性的注释嘛,想起来了嘛,查询查的就是我们的带@Subscribe的方法们。...到此为止我们就能够获得我们打过注解的方法们了。 正式注册 接下来是一段长到要命的代码,不过会尽量给出详细的注释帮助理解。...} 我们发现还没有被用到,但是上述的查询方法中出现了一个共同的特征,就是调用了postSingleEventForEventType(),那就继续深入探寻。...post()方法,但是这里我们需要想起的是我们之前尚未分析的subscribe()中针对粘性事件做出处理的方法。
) 注解方式获取 从下面的代码可以看出,获取注解方法的流程是: 获取类的所有方法 只有一个参数的方法,判断是否有 @subscribe注解 其他都过滤(视情况是否抛异常出来) private void..., 实现的主要区别是Guava多了一个获取超类的过程 - Guava获取所有的超类, 根据每个类的 `getDeclaredMethods` 获取所有的方法,然后判断是否有注解 - Greenrobot...,即便父类的私有方法也是可以的, static也无所谓 Greenrobot 中限制了方法的作用域共有的非静态方法,有且只有一个参数,而且只是对当前类而言 非注解方式 支持非注解方式进行注册,主要借助SubscriberInfoIndex...我们可以倒推一下这个设计思路: 注册,首先是要确定将类的哪些方法注册到 EventBus 排除掉注解方式;还有一种常见的就是我们定义一种方式,可以将我们需要注册的方法直接返回 定义一个接口,用于返回注册类的所有订阅信息...如何获取某注解的方法,这个使用和guava的有些区别,特别是对超类以及作用域的情况处理 非注解方式注册 典型的借用辅助类(SubscriberInfoIndex)来完成预期目标 此外实现的细节上也可以看看
上面仅仅是声明阶段,并没有产生实际效果,只有经过了subscribe之后才开始工作,下面就用上面的代码来分析下整个工作流程。.../*** **该方法会根据声明部分创建完整发布、订阅关系链 *本例子中涉及到下面几个订阅者类:LambdaMonoSubscriber、MapFuseableSubscriber以及...subscribe方法会调用其subscriber(即FilterFuseableSubscriber)的onSubscribe方法,然后进入onSubscribe阶段,onSubscribe调用顺序跟声明阶段相同...,当onSubscribe传到subscribe方法的订阅者时将进入request阶段,request阶段执行顺序跟声明阶段相反,当request阶段执行到数据源端又会触发调用阶段的执行,常见的为subscriber.onNext...方法 publisher.subscribe(subscriber); }
> subscriberClass = subscriber.getClass(); // 根据Class查找当前类中订阅了事件的方法集合,即使用了Subscribe注解、有public...,然后缓存查找到的集合,根据上边的注释可知findUsingInfo()方法会被调用。...(findState); } findUsingInfo()方法会在当前要注册的类以及其父类中查找订阅事件的方法,这里出现了一个FindState类,它是SubscriberMethodFinder...findSubscriberMethods()流程就分析完了,我们已经找到了当前注册类及其父类中订阅事件的方法的集合。...核心的注册事件流程还是我们之前的register()方法中的subscribe()方法,前边分析subscribe()方法时,有一段没有分析的代码,就是用来处理粘性事件的。
简单回顾 如果抛开Rxjava的操作符以及其线程控制的话,Rxjava的最基本使用是比较简单的 第一步,创建被观察者Observable; 第二步,创建观察者Observer/Subscriber..., 被观察者用来通知观察者的notifyObservers()方法; Subscriber(观察者) 一个核心方法 subscribe() 订阅方法, 完成观察者和被观察者之间的订阅; Rxjava..., 构造一个新的Observable对象, 同时借助Observable类的原生构造方法, 将传进来的OnSubscribe对象赋给类中的全局变量onSubscribe; 如此便完成了被观察者Observable...中没有任何事件了, 即列表中所有的事件都被取消订阅了; 那么这个List也就为空; 以上则是Subscriber的核心逻辑; ---- 第三步,下面具体分析订阅的实现 下面小结一下,call()方法在...接着, subscriber.onStart();, 跟进一下onStart(), 可以发现它其实是Subscriber类中的一个空方法; 默认什么都不做,需要我们自己调用的时候去实现; 要把传进来的
: @Subscribe修饰的方法只能有一个参数 @Subscriber修饰的方法必须是public、non-static、non-abstract 当符合了条件并且是@Subscribe注解修饰的方法...这里我们需要分析,当一个事件类型出现了两个及其以上的订阅方法时,就会进入到二层检查;而从代码中可以看到,如果有多个订阅同一事件的方法,那么existing将会在method和findstate中来回切换...如果父类中也有该方法并且也是同一事件的订阅方法,那么在查找父类的订阅方法时,methodClassOld将不为null。...{title='hello', content='world'} readMagazine2(): Magazine{title='hello', content='world'} 可以看到父类中的方法没有打出日志...至此,可以分析完了订阅者是如何将自己订阅到事件中心的,要点有如下几点: EventBus保存了订阅者以及其父类中所有@Subscribe注解了的方法; 订阅者+订阅方法是一个元组; 如果事件是Sticky
>>> typesBySubscriber; EventBus会在对象register时,使用反射机制,遍历对象的方法,将带有@Subscribe标签并且合法的方法加入到typesBySubscriber...; } } 上面的代码主要做两件事:1、通过反射遍历注册对象的方法,获取其中带有@Subscribe标签的方法并且放在一个列表中,最后以注册对象为key,@Subscribe的方法列表作为...要理解register实质上是将订阅对象(比如activity)中的每个带有subscriber的方法找出来,最后获得调用的就是这些方法。...2、后注册的对象中sticky方法能够收到之前的stickyEvent方法的原因是EventBus中维护了stickyEvent的hashMap表,在subsribe注册的时候就遍历其中有没有注册监听stickyEvent...缺点: 1、使用的时候有定义很多event类, 2、event在注册的时候会调用反射去遍历注册对象的方法在其中找出带有@subscriber标签的方法,性能不高。
(subscriber, subscriberMethod); } } } 其中会获取注册对象的类对象,并调用findSubscriberMethods方法获取类中...: // (Class : 方法包装类列表)的缓存 private static final Map<Class<?...最后调用了subscribe方法,入参为注册对象和包装方法类SubscriberMethod,其中又做了缓存: 将注册对象和方法包装类SubscriberMethod重新包装成Subscription对象...的typesBySubscriber这个Map中 private void subscribe(Object subscriber, SubscriberMethod subscriberMethod...clz.getSuperclass(); } if (subscriberMethods.isEmpty()) throw new RuntimeException("该类及其父类没有任何没有订阅方法
register方法注册,并给需要接受和处理消息的方法加上Subscribe注解 public class MainActivity extends AppCompatActivity { @Override...查看EventBus的源码,在EventBus.class中有几个比较重要的变量 eventTypesChahe : 存储Event.class相关的类,包括Event类的父类、以及其实现的接口类 subscriptionsByEventType...跟subscribe中,主要流程: EventBust.getDefault().register(Subscriber) r 找到Subscriber中所有需要接收消息的方法(SubscriberMethod...,使用不同的Poster,在对应的线程中对订阅方法进行反射调用,实现消息接收和处理 总结 EventBus通过对订阅者和发布者的解耦,简化了消息发送和注册的流程,且消息主体可以为任意类的对象,使得消息虽然在...EventBus的代码量不多,算是一个比较轻量的框架,暂不支持跨进程的消息传递,且由于EventBus中维护的Subscriber引用都是强引用,没有及时unregister的话,可能会导致内存泄漏。
(subscriber, subscriberMethod); } } } 1.获取当前订阅者 2.获取当前类中被@Subscriber注解的方法即订阅方法,详情请看findSubscriberMethods...即public、private等 4.只查看修饰符是public的方法 5.返回该方法的参数类型 6.只查看被@subscribe注解的方法,即订阅方法。...7.把订阅方法添加到FindState集合中 二、subscribe 上面findSubscriberMethods查找到所有订阅的方法,接下来需要对这些订阅方法处理,比如订阅方法不能存在重复、按照订阅内容类型为...方法 3.没有找到subscription订阅事件的情况下会抛错No subscribers registered for event或者sendNoSubscriberEvent不为空的情况则发送NoSubscriberEvent...一、lookupAllEventTypes 遍历订阅内容及其父类,存放到eventTypesCache中。 private static List<Class<?
Subscribe流程 我们继续来看EventBus类,分析完了包含的属性,接下来我们看入口方法register() 通过查看源码我们发现,所有的register()方法,最后都会直接或者间接的调用...没错,SubscriberMethodFinder类就是查看传进去的那个 this 对象里面有没有onEvent()方法的。怎么做到的?当然是反射。而且这个类用了大量的反射去查找类中方法名。...还有一个skipMethodVerificationForClasses,看到注释是需要跳过被校验方法的类,校验方法是什么?看看他是干什么的。...这回可以看懂了,就是拿到指定类名的全部订阅方法(以 onEvent 开头的方法),并对每一个方法调用subscribe()。那么再看subscribe()方法。...事件的处理与发送subscribe() subscribe()方法接受四个参数,分别为:订阅者封装的对象、响应方法名封装的对象、是否为粘滞事件(可理解为广播)、这条事件的优先级。
文件或者反射来获得该类中的订阅方法 遍历这个类中的所有订阅方法,挨个添加到订阅列表 拿到类中使用 Subscribe 注解修饰的订阅方法 register() 方法中调用了我们前面介绍的 subscriberMethodFinder.findSubscriberMethods...() 方法得到注册类中使用 Subscribe 注解修饰的方法。...保存订阅方法 下一步就是:遍历这个类中的所有订阅方法,挨个添加到订阅列表,调用 subscribe() 方法: private void subscribe(Object subscriber, SubscriberMethod...,这里简单概括一下,subscribe() 方法主要做了这些事: 判断这个方法之前是否订阅过这个事件,重复订阅会抛出异常 之前没订阅过的话就把方法的参数,也就是我们订阅的事件 与当前类以及该事件的订阅方法的映射关系保存到...带有注释的源码地址 Thanks 本来打算自己画流程图和类图的,但发现前辈画的已经很完美的,而且我也有点困,就借用一下吧 -。-。
Flux 之间无论怎么拼接都会保持链路信息的: 自定义 Mono 和 Flux 的工厂 公共 Subscriber 封装,将 reactor Subscriber 的所有关键接口,都检查当前上下文是否有链路信息...,即 Span,如果没有就包裹上,如果有则直接执行即可。...TracedFlux,和所有 Mono 的代理 TracedMono,其实就是在 subscribe 的时候,用 TracedCoreSubscriber 包装传入的 CoreSubscriber:...GlobalFilter - CommonTraceFilter 我们编写所有我们后面要实现的 GlobalFilter 的抽象类,这个抽象类的主要功能是: 保证继承这个抽象类的 GlobalFilter...* 主要保证 span 的完整性,在某些情况下,span 会半途停止,导致日志中没有 traceId 和 spanId * 参考:https://github.com/spring-cloud/spring-cloud-sleuth
EventBus.getDefault() 默认实例 这里使用了最常见的延迟加载的单例模式,来获取实例,注意下 snchronized 的使用位置,并没有放在方法签名上( 注意这个类不是严格意义上的单例...SubscriberMethod 订阅者回调方法封装类 这个类主要保存的就是订阅者的回调方法相关信息 final Method method; final ThreadMode threadMode...; // 监听的事件类型, 也就是注册方法的唯一参数类型 final Class<?...Subscribe 注解 注解标注在类的唯一参数的公共方法上, 表示这个方法就是我们注册的订阅者回调方法 @Documented @Retention(RetentionPolicy.RUNTIME)...SubscriberMethodFinder 辅助工具类,获取订阅者中的回调方法 顾名思义,这个就是用来获取订阅者类中的所有注册方法的,支持两种方式,一个是上面的注解方式;还有一个则是利用SubscriberInfo
将类中,所有包含@Subscribe 注解的方法捞出来 方法的第一个参数就是 Event, 因为注册的目的是为了实现回调, 所以封装一个类,包含这个Listener对象的引用 + 要执行的方法 上面注册的实际实现和上面的步骤差不多...,不仅将改对象中的所有@Subscribe注解的方法捞出来,连父类中的也不放过;就是这个TypeToken.of(clazz).getTypes().rawTypes(); 从上面的限定,也可以看出,...+方法参数确认(MethodIdentifier的equals方法重写了), 而不是直接用集合的contains方法, 请注意其中的区别) method.isAnnotationPresent(Subscribe.class...& equals 方法没有重写 到此, 注册完毕;注销的方法和上面差不多,唯一的区别是最后一个是向 subscribers 塞数据,一个是从其中删数据而已 题外话 如果我们想获取工程中所有包含某个注解的类可以怎么办...新技能 1.根据class,获取所有超类集合 (EventBus的实际使用中,Event的超类集合都塞入了缓存,加快查询速度) TypeToken.of(concreteClass).getTypes(
{ String topic() default "default-topic"; } @Subscribe要求注解在类中的方法,注解时可指定topic,不指定的情况下为默认的topic(default-topic...的实例和对应的方法,Subscriber对象没有任何特殊要求,就是普通的类不需要继承任何父类或者实现任何接口 package com.artisan.busevent.impl; import com.artisan.busevent.annotations.Subscribe...String topic = subscribe.topic(); //当某topic没有Subscriber Queue的时候创建一个 subscriberContainer.computeIfAbsent...> temp = subscriber.getClass(); //不断获取当前类和父类的所有@Subscribe方法 while (temp !...不能暴露给外部,因此Registry被设计成了包可见的类,所设计的EventBus对Subscriber没有做任何限制,但是要接受event的回调则需要将方法使用注解@Subscribe进行标记(可指定
领取专属 10元无门槛券
手把手带您无忧上云