编写不易,转载请注明(http://shihlei.iteye.com/blog/2426888)!
一 概述
最近看RxJava,其骨架就是使用的观察者模式,所以对观察者模式做个总结,顺便记录一下Guava EventBus的实现(事件监听,其实也相当于观察者模式)
二 观察者模式
1)概述
观察者模式:行为模式,提供一种一对多关系绑定对象的方法,一个对象状态需发生改变,绑定对象能收到通知完成自己的业务更新。
主要成员:
被观察者(Observerable):状态变化,通知所有的观察者。
观察者(observer):接收到“被观察者”的状态变化通知,执行自己的业务。
使用场景:
“被观察者”的状态变化需要通知多个“观察者”,但“被观察者”不需要知道观察者的个数具体细节,他们之间互相独立。一般“观察者”之间相互独立,不会彼此影响。
2)Demo
package x.rx.observer; import java.util.LinkedList; import java.util.List; /** * 观察者模式: * 1)被观察者(Observerable):维护一个观察者队列,事件产生时,回调所以的观察者 * 2)观察者(Observer):注册到"被观察者"中,接收通知,执行自己的业务 * * @author shilei */ public class ObserverPatternDemo { public static void main(String[] args) { Observerable observerable = new Observerable(); observerable.register(() -> { System.out.println("observer1 handle finish!"); }).register(() -> { System.out.println("observer2 handle finish!"); }); observerable.generateEvent(); } /** * 观察者 */ interface Observer { void doEvent(); } /** * 被观察者 */ static class Observerable { private List<Observer> observerList = new LinkedList<>(); /** * 注册观察者 * * @param observer 观察者 */ Observerable register(Observer observer) { observerList.add(observer); return this; } /** * 取消注册 */ Observerable unRegister(Observer observer) { observerList.remove(observer); return this; } /** * 产生事件 */ void generateEvent() { for (Observer observer : observerList) { observer.doEvent(); } } } }
三 Guava EventBus
1) 概述
Guava EventBus 实现了事件监听器模式,主要提供一套基于注解的事件总线,可以灵活的使用。
使用方式:
1)定义一个关注的Event
2)定义一个监听处理方法,@Subscribe 标记,里面实现业务逻辑
3)注册到EventBus即可
2)Demo
(1)依赖
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency>
(2)代码
package x.rx.eventbus; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; /** * guava eventbus * * @author shilei */ public class EventBusDemo { public static void main(String[] args) { EventBus eventBus = new EventBus("demo"); // 注册 eventBus.register(new EventListener()); // 产生事件 eventBus.post(new Event()); } /** * 事件 */ static class Event { } /** * 事件监听器 */ static class EventListener { @Subscribe //这里标记这个方法是事件处理方法 public void handle1(Event event) { System.out.println("handle1 finish! "); } @Subscribe public void handle2(Event event) { System.out.println("handle2 finish! "); } } }
3)源码分析
(1)事件注册到总线:EventBus的register()
private final SubscriberRegistry subscribers = new SubscriberRegistry(this); /** * Registers all subscriber methods on {@code object} to receive events. * * @param object object whose subscriber methods should be registered. */ public void register(Object object) { subscribers.register(object); }
“被观察者”的核心,提供一个队列,维护所有需要通知的观察者,Guava EventBus 这个工作代理给了 SubscriberRegistry , SubscriberRegistry 提供任何类型的事件到事件处理类的绑定关系。
看看注册的细节:
/** * All registered subscribers, indexed by event type. * * <p>The {@link CopyOnWriteArraySet} values make it easy and relatively lightweight to get an * immutable snapshot of all current subscribers to an event without any locking. */ private final ConcurrentMap<Class<?>, CopyOnWriteArraySet<Subscriber>> subscribers = Maps.newConcurrentMap(); /** * Registers all subscriber methods on the given listener object. */ void register(Object listener) { Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener); for (Map.Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) { Class<?> eventType = entry.getKey(); Collection<Subscriber> eventMethodsInListener = entry.getValue(); CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType); if (eventSubscribers == null) { CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<Subscriber>(); eventSubscribers = MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet); } eventSubscribers.addAll(eventMethodsInListener); } }
内部是一个ConcrurentMap,key 是事件class,value是个 CopyOnWriteArraySet<Subscriber> 用于通知,最重要的方法 findAllSubscribers(listener) ,他会通过反射,找到 @Subscribe 注解的方法,并关联他绑定的事件。获取到就添加到 subscribers(类型ConcrurentMap)中,这个subscribers 维护了所有的事件和事件处理器的绑定关系。
看看findAllSubscribers(listener) 的细节:
/** * Returns all subscribers for the given listener grouped by the type of event they subscribe to. */ private Multimap<Class<?>, Subscriber> findAllSubscribers(Object listener) { Multimap<Class<?>, Subscriber> methodsInListener = HashMultimap.create(); Class<?> clazz = listener.getClass(); for (Method method : getAnnotatedMethods(clazz)) { Class<?>[] parameterTypes = method.getParameterTypes(); Class<?> eventType = parameterTypes[0]; methodsInListener.put(eventType, Subscriber.create(bus, listener, method)); } return methodsInListener; }
相关推荐
jar包,亲测可用
Guava的EventBus源码学习,基于Guava的18.0版本 分析者: ###1. 背景简介 EventBus是google的一个Java工具包其中的一个工具类,类似的有多个版本其中包括移植到Android端的 和改良的,功能基本都是一样的。此处主要...
eventBus android 跨页面异步传输数据 可用于异步网络请求和 异步跨页面传数据
jar包,亲测可用
主要介绍了EventBus与Spring Event区别,需要的朋友可以参考下
SNAPSHOTMaven依赖<dependency><groupId>com.woter.fact</groupId><artifactId>fact-bus</artifactId><version>1.0.0-SNAPSHOT</version></dependency>功能描述fact-bus 是基于guava整合spring实现EventBus;...
├─Google Guava 第19讲-Guava之EventBus和NIO2.0 WatchService综合实战.wmv ├─Google Guava 第20讲-实战:手动实现一个EventBus-01快速搭建程序结构.wmv ├─Google Guava 第21讲-实战:手动实现一个EventBus-...
汪文君Google Guava 代码。Guava之函数式接口、Guava EventBus源码剖析以及优缺点总结
跟着 Guava、Spring 学习如何设计观察者模式.doc
EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。 ...
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用
jar包,亲测可用