`

请您先登录,才能继续操作

观察者模式和Tomcat, Guava的EventBus中的简单实现

 
阅读更多

1. 简介

    观察者模式,也叫发布-订阅模式, 定义了一对多的依赖关系. 多个观察者监听一个主题.

    主题发生变化时, 观察者得到通知, 然后选择后续的动作. 

    这里的得到通知, 根据是主题主动通知还是观察者主动请求分为推模型和拉模型

    类图如下:

    
                

    上图是观察者模式的最简单实现,类似于OS中的最小系统. 和一般面向对象语言的设计模式一样, 都会使用到多态, 利于程序的可扩展性.类图中分为4个角色:

    抽象主题: Subject 

    具体主题: ConcreteSubject

    抽象观察者: Observer

    具体观察者: ConcreteObserver

    

    观察者只有一个方法update(). 主题Subject中, 有3个方法 add() 或 register(), remove(), notify().

    最主要的是notify(), 一般是主题遍历自己维护的观察者队列中的所有观察者, 一次调用观察者的update(). 

    这里有一个思维的误区, 观察者收到通知,然后自己选择是否进行操作. 实际上是一个被动的过程. 

    首先观察者将自己注册到主题中, 主题维护一个队列,用于持有该观察者的引用. 之后由主题调用观察者的方法进行更新.

 

2. tomcat中的应用

    这里借用网络上的一个例子. 

    tomcat中,定义了一个LifeCycleSupport类, 协助管理观察者, 其实也是对观察者模式的一个延伸. 

    fireLifeCycleEvent里面有一个fireLifeCycleEvent()方法,也就是类图中的notify().

   

public void fireLifeCycleEvent (String type, Object data) {
     LifeCycleEvent event = new LifeCycleEvent(lifecycle, type, data);
     LifeCycleListener linterested = listeners;
     for (int i = 0; i < interested.length; i++) {
           interested[i].llfecycleEvent(event);
     }

     

     参数中的LifecycleEvent 是tomcat定义的事件, 如下:

   

public LifecycleEvent (Lifecycle lifecycle, String type, Object data) {
    super(lifecycle);
    this.type = type;
    this.data = data;
}

   

    从上可知,tomcat中观察者的流程如下:

    1. 将观察者listener加到LifeCycleSupport的listener数组中

    2. 主题做某些动作时, 生成一个LifeCycleEvent对象, 标明这是一个什么样的事件. 之后由LifeCycleSupport通知listener中的每一个观察者,

    3. listener会根据事件的类型, 做出对应的动作
 

3. 观察者应用的场景

    观察者适用于几个场景

    ①一个对象的改变需要通知到多个对象. 但是又不清楚具体有多少个对象需要通知,. 

       观察者使用了集合 + 接口实线了解耦, 使Subject和Observer都只知道对方是一个接口, 不用关心具体的子类

    ②多级联动关系, 比如GUI编程中. panet A 中有多个panet B , 当panet A 需要改变时, panet B 大小也需要随着改变, 整体全部变化

    ③ 消息分发场景, 比如QQ广播, 新闻推送. 当然这些功能并非一定依靠观察者才能实现

 

4. Guava中的实现

    guava中的观察者非常简单. 只需要在指定的方法加上注解 @Subscribe即可.

    

public class Event {
    @Subscribe
    public void sub(String msg) {
       //some statement
       System.out.println("sub method is called."  + msg);
    }
}


public class Client {
public static void main(String[] args) {
        EventBus eventbus = new EventBus();
        eventbus.register(new Event());
        eventbus.post("Guava EventBus is post"); //触发事件
    }
}

 

   EventBus的大体实现逻辑

   调用eventbus.register()时, eventbus实例会将事件对象放到SetMultimap<Class<?>, EventSubscriber> 中, 这是一个线程安全的容器, unregister()方法也在其中

 

    再说eventbus.post()方法. eventbus实例将参数匹配的对象放到事件队列 ThreadLocal<Queue<EventWithHandler>> eventsToDispatch中, 等待事件分发完成. 再做统一的事件消费.

这里所有的容器都是线程安全的, 本地线程, 同步, 同时使用ReentranceLock.

 

    另外EventBus提供了一个异步容器 AsyncEventBus, 示例代码如下:

    

public void asyncEventBus() {
    AsyncEventBus eventbus = new AsyncEventBus(Executor.newFixedThreadPool());
    eventbus.register(new Event());
    eventbus.post("async event bus called");
}

   

    AsyncEventBus实线逻辑中, 事件注册, 移除, 和同步的EventBus是相同的逻辑, 不同的是事件的分发和消费.它的事件消费,不再使用ThreadLocal, 而是换成了ConcurrentLinkedQueue<EventWithHandler> eventsToDispatch. 消费事件任务是一个线程池, 一个Executor的实现, 这个实现需要开发自己定义.

 

   最后是deadEvent, 使用场景如下:

   

public static void main(String[] args) {
        EventBus eventbus = new EventBus();
        eventbus.register(new Event());
        eventbus.post(123); //这里应该是使用String对象作为参数,但这里参数类型是int
    }

 

    这里@Subscribe方法的参数类型是String, 但是@post中的参数类型是int, 导致@Subscribe方法无法被消费, EventBus会将此事件当做一个deadEvent. 

  • 大小: 17.3 KB
分享到:
评论

相关推荐

    跟着 Guava、Spring 学习如何设计观察者模式.doc

    在Java中,Guava和Spring框架都提供了实现观察者模式的工具。 Guava的EventBus是观察者模式的一个实例,它简化了事件发布和订阅的过程。EventBus允许你定义事件的发布者(即被观察者)和事件的订阅者(即观察者)。...

    camel-guava-eventbus-2.11.0-sources.jar

    jar包,亲测可用

    Guava-Event-Bus:Guava的EventBus源码学习

    EventBus 是一个基于事件的一个发布/订阅框架,通过解耦发布者和订阅者简化事件传递,这里的事件可以理解为消息,本文中统一称为事件也就是 Event。通过EventBus可以简化生产者/消费者 这种模型,同时又可以通过...

    观察者模式

    9. **扩展**:除了Java内置的`Observer`和`Observable`,开发者还可以使用第三方库如Guava的`EventBus`,或者Spring框架的`ApplicationEvent`和`ApplicationListener`,这些都提供了更高级的观察者模式实现。...

    eventBus android 跨页面异步传输数据

    eventBus android 跨页面异步传输数据 可用于异步网络请求和 异步跨页面传数据

    EventBus与Spring Event区别详解(EventBus 事件机制,Spring Event事件机制)

    EventBus和Spring Event都是基于事件机制的异步处理方式,但它们有着不同的设计理念和实现方式。在本文中,我们将详细剖析EventBus和Spring Event的区别,帮助读者更好地理解和选择合适的事件机制。 EventBus事件...

    JAVA 发布-订阅(观察者)模式

    在实际应用中,Java的发布-订阅模式不仅限于`Observable`和`Observer`,还可以结合`EventBus`库如`Guava EventBus`或`Otto`等,它们提供了更强大和灵活的事件传递机制。这些库允许异步事件处理,支持事件分发的过滤...

    不加密Google Guava视频教程.txt

    ├─Google Guava 第13讲-Guava之CharStreams和ByteStreams源码剖析(比较简单).wmv ├─Google Guava 第14讲-Guava之Closer使用和原理剖析,非常重要.wmv ├─Google Guava 第15讲-Base64原理详解,手动实现base...

    fact-bus:基于guava整合spring实现EventBus;具体详情请访问:https

    SNAPSHOTMaven依赖&lt;dependency&gt;&lt;groupId&gt;com.woter.fact&lt;/groupId&gt;&lt;artifactId&gt;fact-bus&lt;/artifactId&gt;&lt;version&gt;1.0.0-SNAPSHOT&lt;/version&gt;&lt;/dependency&gt;功能描述fact-bus 是基于guava整合spring实现EventBus;...

    SpringBoot+EventBus使用教程示例代码

    在本文中,我们将深入探讨如何在SpringBoot应用中使用EventBus,这是一个基于Guava库的事件总线系统。EventBus的引入使得松耦合的组件间通信变得更加简单和高效。让我们一起通过步骤来理解这个“SpringBoot+EventBus...

    guava-18.0(guava-18.0.jar和guava-18.0-sources.jar)

    8. **事件监听**:Guava的EventBus可以方便地实现发布/订阅模式,简化事件驱动的编程。 9. **枚举集与常量**:Guava提供了ImmutableEnumSet和ImmutableSet.of()等方法,创建不可变且高效的枚举集合。 `guava-18.0-...

    camel-guava-eventbus-2.11.1.jar

    jar包,亲测可用

    Guava-EventBus-APT:注释处理器,用于检查使用@Subscribe注释进行注释的方法是否只有一个参数

    在 Guava EventBus 的使用中,`@Subscribe` 注解是核心概念,它标记了那些监听并处理事件的方法。然而,为了保证 EventBus 的正确使用,开发者需要注意`@Subscribe` 注解的方法应遵循一定的规范,比如方法参数的数量...

    guava_programming.zip

    EventBus是一种观察者模式的实现,它允许组件之间通过发布和订阅事件进行通信,而不必显式地相互依赖。通过注册到EventBus的订阅者可以接收特定类型的事件,而发布者只需发送事件,无需关心哪个或哪些订阅者会处理...

    EventBus消息总线

    EventBus是Guava的事件处理机制,是设计模式中的观察者模式(生产/消费者编程模型)的优雅实现。对于事件监听和发布订阅模式,EventBus是一个非常优雅和简单解决方案,我们不用创建复杂的类和接口层次结构。 ...

    guava-18.0资料

    4. **并发支持**:Guava提供了更高级的并发工具,如RateLimiter(限流器)、Service(服务管理)和ListenableFuture(监听型未来)等,使得在多线程环境中编写高效、安全的代码变得更加简单。 5. **字符串处理**:...

    google guava 中文教程

    Guava中的原子类如AtomicInteger、AtomicLong等,以及WeakReference、SoftReference等内存管理工具,帮助开发者实现线程安全的数据结构和高效内存管理。 八、其他特性 Guava还包含了一些其他实用功能,如事件总线...

    使用google guava 实现定时缓存功能

    综上所述,Google Guava的定时缓存功能使得我们能够轻松地在Java应用中实现高效的缓存机制,有效减少计算和网络请求的负担,提升整体性能。通过灵活的配置和丰富的API,我们可以根据具体需求定制合适的缓存策略。在...

    Node.js-EventBus简单使用实例学习使用开源库提高开发效率与速度

    针对Android平台,"Node.js-EventBus简单使用实例学习使用开源库提高开发效率与速度"这个主题聚焦于如何利用EventBus库来实现这一目标。EventBus是一种发布/订阅事件总线,它简化了组件之间的通信,使得Android应用...

    Guava 工程项目包 有实例

    通过深入研究 "guava-master" 文件中的源代码,可以了解到 Guava 的具体实现细节,这对于理解和优化自己的 Java 项目非常有益。此外,了解并掌握 Guava 的使用,能够使你的代码更加简洁、高效,同时减少潜在的错误。

Global site tag (gtag.js) - Google Analytics