介绍

观察者模式的本质是“定义对象之间的一对多依赖关系,以便当一个对象改变状态时,其所有依赖关系都会得到通知并自动更新。” GoF。 观察者模式是发布/订阅模式的子集,它允许许多观察者对象查看事件。

可以在不同的情况下使用此模式,但总而言之,可以说观察者模式可以在对象应该能够将消息通知其他对象并且您不希望这些对象紧密耦合时应用。 就我而言,当异步事件应通知一个或多个图形组件时,我使用了这种模式。

可以使用临时解决方案或使用java.util.Observer/Observable类来实现此模式。 但是我的项目总是用Spring开发的,无论是Web还是桌面应用 。 因此,在当前文章中,我将解释如何使用Spring实现Observer模式。

手扶

Spring ApplicationContext中的事件处理是通过ApplicationEvent类和ApplicationListener接口提供的。 如果将实现ApplicationListener接口的bean部署到上下文中,则每次将ApplicationEvent发布到容器时, ApplicationListener都会接收到它。
Spring带有内置事件,例如ContextStartedEventContextStoppedEvent ,但是您也可以创建自己的自定义事件。

为了开发自己的事件,需要三个类, 观察者角色, 可观察角色和事件观察者是那些接收事件并且必须实现ApplicationListener类的人。 可观察类负责发布事件,并且必须实现ApplicationEventPublisherAware 。 最后, 事件类必须扩展ApplicationEvent

编码

我要实现的是Observer模式的Wikipedia示例( http://en.wikipedia.org/wiki/Observer_pattern#Example ),但是使用Spring Events而不是Observer / Observable Java类。 该示例是一个基本的发布/订阅示例,其中一个String消息从一个模块发送到另一个模块。
让我们创建MessageEvent 。 此事件包含一个String,它表示我们要发送的消息。 这是一个从ApplicationEvent扩展的简单类。

public class MessageEvent extends ApplicationEvent {*** *private static final long serialVersionUID = 5743058377815147529L;private String message;public MessageEvent(Object source, String message) {super(source);this.message = message;}@Overridepublic String toString() {StringBuilder builder = new StringBuilder();builder.append('MessageEvent [message=').append(message).append(']');return builder.toString();}}

下一个类是Observable类。 此类必须实现ApplicationEventPublisherAware 。 此接口使用ApplicationEventPublisher作为参数定义了一个setter方法。 此参数用于发布事件。
在当前的实现中,该代码还实现了Runnable接口,因此用户可以从控制台输入中进行创建,

public class EventSource implements Runnable, ApplicationEventPublisherAware {private ApplicationEventPublisher applicationEventPublisher = null;public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.applicationEventPublisher = applicationEventPublisher;}public void run() {final InputStreamReader isr = new InputStreamReader(System.in);final BufferedReader br = new BufferedReader(isr);while (true) {try {String response = br.readLine();System.out.println(Thread.currentThread().getName());this.applicationEventPublisher.publishEvent(new MessageEvent(this, response));} catch (IOException e) {e.printStackTrace();}}}}

Observer类甚至更简单。 实现ApplicationListener接口。 发布事件时将调用onApplicationEvent方法。 看到它是一个通用接口,因此不需要强制转换。 这不同于java.util.Observer类。

public class ResponseHandler implements ApplicationListener<MessageEvent> {public void onApplicationEvent(MessageEvent messageEvent) {System.out.println(Thread.currentThread().getName());System.out.println(messageEvent);}}

在应用程序上下文文件中,您同时注册了ApplicationListenerApplicationEventPublisherAware Bean。

最后是一个主类来测试系统。 创建一个线程以执行多个异步事件。

public class MyApp {public static void main(String args[]) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext('classpath:META-INFspringapp-context.xml');EventSource eventSource = applicationContext.getBean('eventSource', EventSource.class);Thread thread = new Thread(eventSource);thread.start();}}

因此,启动程序并编写一些内容以进行控制台。 您将看到类似以下内容:
你好 Thread-0 Thread-0 MessageEvent [message = hello]
我输入了“ hello ”消息,并打印了事件发布者的线程名 。 然后发送事件并打印处理程序线程名称 。 最后显示接收到的事件。 有一件事情应该引起您的注意。 发送者( Observable )和接收者( Observer )都在同一线程中执行; 默认情况下,事件侦听器同步接收事件。 这意味着publishEvent()方法将阻塞,直到所有侦听器都已完成对事件的处理为止。 这种方法有很多优点(例如,重用事务上下文等),但是在某些情况下,您希望每个事件都在新线程中执行, Spring也支持此策略。

Spring中 ,负责事件管理的类是SimpleApplicationEventMulticaster 。 此类将所有事件多播到所有注册的侦听器,让侦听器忽略它们不感兴趣的事件。默认行为是在调用线程中调用所有侦听器。

现在,我将解释如何初始化Spring Event Architecture以及如何进行修改。 默认情况下,当ApplicationContext为 启动后,它将调用initApplicationEventMulticaster方法。 此方法验证是否存在与类型ApplicationEventMulticaster的ID applicationEventMulticaster的bean。 如果是这样,则使用已定义的ApplicationEventMulticaster ,否则,将创建具有默认配置的新SimpleApplicationEventMulticaster

SimpleApplicationEventMulticaster具有可用于指定哪些java.util.concurrent.Executor将执行事件setTaskExecutor。 因此,如果您希望每个事件在不同的线程中执行,那么一个好的方法是使用ThreadPoolExecutor 。 如上一段所述,现在我们必须显式定义SimpleApplicationEventMulticaster而不是 使用默认的。 让我们实现:

<beans xmlns='http:www.springframework.orgschemabeans' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns:context='http:www.springframework.orgschemacontext' xmlns:task='http:www.springframework.orgschematask' xsi:schemaLocation='http:www.springframework.orgschematask http:www.springframework.orgschemataskspring-task-3.0.xsd http:www.springframework.orgschemabeans http:www.springframework.orgschemabeansspring-beans-3.0.xsd http:www.springframework.orgschemacontext http:www.springframework.orgschemacontextspring-context-3.0.xsd'><bean id='eventSource' class='org.asotobu.oo.EventSource' > <bean id='responseHandler' class='org.asotobu.oo.ResponseHandler' > <task:executor id='pool' pool-size='10' > <bean id='applicationEventMulticaster'        class='org.springframework.context.event.SimpleApplicationEventMulticaster'><property name='taskExecutor' ref='pool' > <bean><beans>

首先,必须将SimpleApplicationEventMulticaster定义为ID为applicationEventMulticaster的bean。 然后设置任务池,然后我们重新运行主类。 输出将是:
你好 线程1 池1 MessageEvent [message = hello]
请注意,现在发送方和接收方线程有所不同。

当然,您可以为更复杂的操作创建自己的ApplicationEventMulticaster 。 您只需要实现ApplicationEventMulticaster并使用applicationEventMulticaster bean名称定义它,事件将根据您自己的策略执行。

希望现在您的Spring桌面应用程序可以充分利用Spring事件来分隔模块。

下载代码。

参考:来自JCG合作伙伴 Alex Soto的Spring Events观察者模式,来自One Jar To Rule All All博客。

翻译自: https://www.javacodegeeks.com/2012/08/observer-pattern-with-spring-events.html

Spring事件的观察者模式相关推荐

  1. spring观察者模式_Spring事件的观察者模式

    spring观察者模式 介绍 观察者模式的本质是"定义对象之间的一对多依赖关系,以便当一个对象改变状态时,其所有依赖关系都会被通知并自动更新". GoF. 观察者模式是发布/订阅模 ...

  2. spring事件驱动模型--观察者模式在spring中的应用

    spring中的事件驱动模型也叫作发布订阅模式,是观察者模式的一个典型的应用,关于观察者模式在之前的博文中总结过,http://www.cnblogs.com/fingerboy/p/5468994. ...

  3. spring 事件监听

    用一个简单的例子来实现spring事件监听的功能 这个例子主要功能是,记录那些用户是第一次登入系统,如果用户是第一次登入系统,则调用spring的事件监听,记录这些用户. 主要用到的spring的类和 ...

  4. Spring5源码 - 11 Spring事件监听机制_源码篇

    文章目录 pre 事件监听机制的实现原理[观察者模式] 事件 ApplicationEvent 事件监听者 ApplicationEvent 事件发布者 ApplicationEventMultica ...

  5. Spring5源码 - 10 Spring事件监听机制_应用篇

    文章目录 Spring事件概览 事件 自定义事件 事件监听器 基于接口 基于注解 事件广播器 Spring事件概览 Spring事件体系包括三个组件:事件,事件监听器,事件广播器 事件 Spring的 ...

  6. java观察者模式在spring中的应用_利用spring自己实现观察者模式

    利用spring,自己实现的一个观察者模式,写着玩玩,目的是为了加深理解,下次用Spring自带的玩一玩. 首先我们定义一个侦听类接口 package com.hyenas.common.listen ...

  7. Spring事件机制详解

    一.前言 说来惭愧,对应Spring事件机制之前只知道实现 ApplicationListener 接口,就可以基于Spring自带的事件做一些事情(如ContextRefreshedEvent),但 ...

  8. java观察者模式在spring中的应用_Spring源码之spring中的观察者模式和监听器的使用...

    声明:本文根据鲁班学院子路老师spring中观察者模式课程整理得来 观察者模式特点: 被观察者持有监听的观察者的引用. 被观察者支持增加和删除的观察者. 被观察者状态改变通知观察者. JDK中观察者i ...

  9. Guava、Spring 如何抽象观察者模式?

    什么是观察者模式 观察者模式 是一种行为设计模式,允许定义一种订阅通知机制,可以在对象(被观察者)事件发生时通知多个 "观察" 该对象的观察者对象,所以也被称为 发布订阅模式 其实 ...

最新文章

  1. python数据驱动读取用例_Python Selenium 之数据驱动测试
  2. 区块链BaaS云服务(22)趣链BitXHub跨链平台
  3. 【Java】 5.8 继承和组合
  4. php小结,PHP编程小结
  5. 计算机电路逻辑分析基础知识答案,计算机电路基础试卷及答案.pdf
  6. python3爬虫初探(六)之EXCEL
  7. java 获取组件大小_java - 如何初始化取决于组件大小的图像抓取? - 堆栈内存溢出...
  8. (整理)REHL6.5_Yum安装Reids
  9. 机器学习实践中的 7 种常见错误
  10. java 大字符集_JAVA语言之java 乱码 字符集编码
  11. funcode黄金矿工(提高篇)
  12. 自己的部分小软件合计 2000 - 2013
  13. Django 优秀资源大全
  14. R语言ggplot2可视化条形图:通过双色渐变配色颜色主题可视化条形图
  15. HTML5+app开发学习之IOS打包篇
  16. 有一种加班,叫别人还没走!
  17. 大学计算机类专业详解,多伦多大学计算机相关专业解析
  18. python-Matplotlib数据可视化
  19. 幼儿园小班上计算机课 作业内容是手口一致,幼儿园1-10数字手口一致,对物数数教案...
  20. 自勉三句话--关于职业生涯规划

热门文章

  1. idea部署springboot项目到外部tomcat
  2. java生产者实现kafka拦截器
  3. java流与文件——操作文件
  4. boot gwt_带Spring Boot的GWT
  5. javafx按钮设计风格_Java,JavaFX的流畅设计风格按钮,切换按钮和工具提示
  6. java mic波形识别_会议季Mic Drop:您不应该错过的13场Java演讲
  7. 事件驱动程序设计_简单的事件驱动设计
  8. redis开启redis_Redis聚类
  9. jconsole 使用_我的Wiki:使用JConsole对WildFly(或JBoss AS7)进行远程JMX访问
  10. 关于高效企业测试的思考(1/6)