如何在Spring 3.x中使用事件

创建松耦合应用程序的概念和技术很多,Event是其中之一。 事件可以消除代码中的许多依赖关系。 有时没有事件,很难实施SRP *。 Java中的Observable接口可以帮助我们实现事件(通过Observer Pattern)。

但是,等等,这篇文章的目标是关于Spring Event的快速教程。 Spring具有一些用于创建事件驱动应用程序的好工具。 您可以在一个bean中引发一个特定的事件,然后在另一个bean中监听它。

想象一个简单的应用程序具有以下要求:

  • 有些订单的状态可能不同
  • 当订单处于“已交付”或“已推迟”状态时,我们需要向客户发送电子邮件

满足需求的第一个(但不是最好的)解决方案是在我们的订单模型中发送电子邮件,但是存在一些缺陷:

  • 订单不负责发送电子邮件。
  • 如果您遵循域驱动原则,那么Order是一个域对象,但Email Sender可能是一项服务(不同于Domain Service),因此您不能在模型中使用它。

另一个解决方案是在更改其订单状态后在Order模型中引发一些事件。 我不关心订购在引发此事件之后会发生什么。 在我们的示例中,我们需要收听特定类型的事件,对其进行分析并开展一些业务(发送电子邮件)。

@Configurablepublic class Order implements ApplicationEventPublisherAware {private final String orderId;private final Date createDate;private final CustomerInfo customerInfo;private ApplicationEventPublisher eventPublisher;private Date lastUpdateDate;private Status status;public Order(String orderId, CustomerInfo customerInfo) {this.orderId = orderId;this.customerInfo = customerInfo;status = Status.MODIFIABLE;this.createDate = new Date();this.lastUpdateDate = this.createDate;}public String getOrderId() {return orderId;}public void checkOut() {if (status == Status.DELIVERED) {throw new IllegalStateException(String.format("Order is already delivered"));}this.status = Status.CHECKED_OUT;this.lastUpdateDate = new Date();}public void deliver() {if (this.status != Status.CHECKED_OUT && this.status != Status.POSTPONED) {throw new IllegalStateException(String.format("Order status should be CHECKED OUT for delivery to be called. but is : %s", status));}this.status = Status.DELIVERED;this.lastUpdateDate = new Date();this.eventPublisher.publishEvent(new OnOrderDelivered(this));}public void postponeDelivery() {if (status != Status.CHECKED_OUT && status != Status.POSTPONED) {throw new IllegalStateException(String.format("Can not postpone delivery in this state: %s", status));}this.status = Status.POSTPONED;this.lastUpdateDate = new Date();this.eventPublisher.publishEvent(new OnOrderPostponed(this));}public Status getStatus() {return status;}public CustomerInfo getCustomerInfo() {return customerInfo;}public Date getLastUpdateDate() {return lastUpdateDate;}public Date getCreateDate() {return createDate;}@Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {this.eventPublisher = applicationEventPublisher;}public static enum Status {MODIFIABLE,CHECKED_OUT,POSTPONED,DELIVERED,CANCELED;}}

如您所见,Order是一个可配置的类,如果您以前从未使用过此概念,请不要为之苦恼。 对于这篇文章,您只需要知道可配置类可以使用new关键字在任何地方创建,但是它们是由spring管理的,因此您可以在其中注入其他bean或与它们一起使用大多数spring设施。 我保证会尽快发布有关它的文章。

Order类实现org.springframework.context.ApplicationEventPublisherAware接口。 此接口具有名称为setApplicationEventPublisher的setter方法,该方法表示要在您的类中使用的ApplicationEventPublisher 。 如您在deliver方法中所见,我们使用该对象发布事件( this.eventPublisher.publishEvent(new OnOrderDelivered(this)) )。 您可以发布扩展org.springframework.context.ApplicationEvent每个事件。 当订单被推迟时,我们引发了另一个事件OnOrderPostponed

public abstract class OnOrderStatusChanged extends ApplicationEvent {private final Order order;public OnOrderStatusChanged(Order source) {super(source);this.order = source;System.out.println(String.format("Order:%s status is changed to %s", source.getOrderId(), source.getStatus()));}public Order getOrder() {return order;}}public class OnOrderDelivered extends OnOrderStatusChanged {public OnOrderDelivered(Order order) {super(order);}}public class OnOrderPostponed extends OnOrderStatusChanged {public OnOrderPostponed(Order order) {super(order);}}

OnOrderStatusChanged是一个抽象类,OnOrderDelivered和OnOrderPostponed对其进行了扩展。 到现在为止,我们可以创建活动并发起活动。 现在,如果您创建一个弹簧测试并调用订单的传递方法,您将看到“ Order:X状态已更改为DELIVERED”。最后一步是在发布这些事件时执行某些操作。 这些方法提出后,我们希望向客户发送电子邮件。 另外,对于客户来说,在订单处于交付状态时发布产品也很有价值。 侦听器是实现通用ApplicationListener接口的简单Bean。 此接口中的参数类型是您要监听的事件的类型。 可以将参数类型定义为父级,并侦听其所有子级。 例如在我们的模型中,如果我们使用OnOrderStatusChanged侦听器将捕获OnOrderDeliveredOnOrderPostponed所有事件

在我们的方案中,它可能适合发送电子邮件。 但是我们不使用此模型,而是为它们创建两个不同的侦听器。

如您所见,它们的代码非常简单

@Servicepublic class OrderDeliveredEmailSender implements ApplicationListener,Ordered {@Overridepublic void onApplicationEvent(OnOrderDelivered event) {System.out.println(String.format("Message sent for delivered order to:%s ORDER-ID:%s",event.getOrder().getCustomerInfo().getEmail(),event.getOrder().getOrderId()));}@Overridepublic int getOrder() {return 100;}}@Servicepublic class OrderPostponedEmailSender implements ApplicationListener {@Overridepublic void onApplicationEvent(OnOrderPostponed event) {System.out.println(String.format("Message sent for postponed order to:%s ORDER-ID:%s", event.getOrder().getCustomerInfo().getEmail(), event.getOrder().getOrderId()));}}

当引发对应事件时,这两个bean将触发onApplicationEvent。 为了将产品发布给客户,我们需要为OnOrderDelivered事件创建另一个监听器。

@Servicepublic class OnOrderDeliveredPost implements ApplicationListener,Ordered {@Overridepublic void onApplicationEvent(OnOrderDelivered onOrderDelivered) {System.out.println(String.format("Order:%s is posting for customer.",onOrderDelivered.getOrder().getOrderId()));}@Overridepublic int getOrder() {return 1000;}}

如您所见,此侦听器将在状态为“已交付”时将产品发送给客户。 但是等一下什么是Ordered接口? 如果您没有使用org.springframework.core.Ordered接口,那么知道使用此接口可以定义集合中bean之间的顺序是很有价值的。 在我们的方案中,客户喜欢在将产品发布给他之前收到一封电子邮件。 为此,这两个类实现了Ordered接口,不要忘记最低的顺序具有最高的优先级。

*单一责任原则

  • 您可以从以下网址下载源代码: https : //github.com/psycho-ir/spring-event.git

参考: Just另一个Java博客博客中的JCG合作伙伴 Soroosh Sarabadani的Spring 3.x中的如何使用Events 。

翻译自: https://www.javacodegeeks.com/2013/08/how-to-use-events-in-spring-3-x.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php识别地址,实现地址自动识别实例(PHP)

具体问题具体分析!代码实现基于laravel完成。一个laravel完整的功能得具备这些:路由route,Model, View, Controller, 我这里用的有依赖注入服务容器等功能,当然,用到地址,你首先要有地址库。。。下面来看看…

kubernetes cpu限制参数说明

docker CPU限制参数 Option Description --cpus<value> Specify how much of the available CPU resources a container can use. For instance, if the host machine has two CPUs and you set --cpus"1.5", the container is guaranteed at most one and …

工业机器人用铸铁牌号_常用铸铁牌号

常用铸铁的牌号、组织与性能常用铸铁的牌号、组织与性能铸铁中的石墨形态、尺寸以及分布状况对性能影响很大。铸铁中石墨状况主要受铸铁的化学成分及工艺过程的影响。铸铁中石墨形态(片状或球状)在铸造后即形成&#xff1b;也可将白口铸铁通过退火&#xff0c;让其中部分或全部…

浏览器拦截打开新窗口情况总结

在打开一个新窗口时&#xff0c;由于浏览器的安全机制&#xff0c;用户未始终允许的情况下&#xff0c;可能会触发到浏览器拦截&#xff0c;无法正常直接弹出。 网上有很多给出解决方案的只言片语&#xff0c;不够全面&#xff0c;所以针对自己遇到的问题做了详细的情况分析。…

什么叫组件化开发

1、https://www.zhihu.com/question/29735633 &#xff08;什么叫组件化开发&#xff09;转载于:https://www.cnblogs.com/smght/p/8694229.html

php5.5 session,(五)ThinkPHP实践之Session驱动-TTLSA

Session驱动是指Session在thinkphp中的存储驱动&#xff0c;通过不同的方式&#xff0c;可以将Session存储在不同的“容器”中对Session有兴趣的的朋友可以查阅相关资料&#xff0c;本篇仅针对thinkphp的session驱动进行讲解一、DB驱动知识点&#xff1a;1、thinkphp框架默认DB…

Java 8备忘单中的可选

Java 8 java.util.Optional<T>是scala.Option[T]和Data.Maybe在Haskell中的较差表亲。 但这并不意味着它没有用。 如果您不熟悉此概念&#xff0c;请将Optional想象为可能包含或不包含某些值的容器。 就像Java中的所有引用都可以指向某个对象或为null &#xff0c; Optio…

SQL Server2012 安装方法

请看 https://blog.csdn.net/monkeybrothers/article/details/78021848转载于:https://www.cnblogs.com/nanqiang/p/9596528.html

卡方线性趋势检验_SPSS:趋势卡方检验

SPSS&#xff1a;趋势卡方检验毕业季接近尾声&#xff0c;通过答辩的各位同学们即将开始新的旅程。回顾论文点滴&#xff0c;想必既有心酸又充满欣慰。回顾毕业生咨询论文写作得到一个启示与各位分享&#xff1a;论文完成的过程也是还原临床研究的过程&#xff0c;论文收集资料…

让 Chrome 崩溃的一行 CSS 代码

一般的 CSS 代码只会出现 UI 版式或者兼容性方面的小问题。但这里我们要分享一行有趣的 CSS&#xff0c;它可以直接让你的 Chrome 页面挂掉 :) 复现 在 Chrome 里打开一个稍复杂的页面&#xff0c;比如知乎或者掘金打开开发者工具&#xff0c;为页面 <body> 增加样式 s…

oracle块空间的使用,Oracle管理存储架构(二)--Oracle管理数据块空间

1、数据块的概念数据块是数据库中最小的分配单元&#xff0c;块是数据库使用的最小的I/O单元&#xff0c;由一个或多个操作系统block组成。数据块由block header 、free space 、data 组成&#xff0c;oracle 10g 标准块是8k&#xff0c;支持2~32k。块头&#xff1a;包含块地址…

在JBoss 7中使用HA Singleton

不久前&#xff0c;我不得不更改Quartz Scheduler的标准集群行为&#xff0c;并使其能够在不同步数据库的情况下工作。 当然&#xff0c;有很多选择可以做到这一点&#xff0c;但是由于我是简单性的忠实拥护者&#xff0c;因此我决定使用标准的Spring Scheduled配置&#xff0c…

软件目录结构规范

软件目录结构规范 为什么要设计好目录结构? "设计项目目录结构"&#xff0c;就和"代码编码风格"一样&#xff0c;属于个人风格问题。对于这种风格上的规范&#xff0c;一直都存在两种态度: 一类同学认为&#xff0c;这种个人风格问题"无关紧要"…

软件工程的基本步骤

&#xff11;问题定义 问题定义阶段必须回答的关键问题&#xff1a;“要解决的问题是什么&#xff1f;”如果不知道问题是什么就试图解决这个问题&#xff0c;显然是盲目的&#xff0c;只会白白浪费时间和金钱&#xff0c;最终得出 的结果很可能是毫无意义的。尽管确切地定义问…

matlab norm函数使用_matlab norm(a-b)

(示例: X(1:10,1:10)zeros(10,10),LX[X,X;X,X]) Matlab 中冒号(: )的使用方法小结: (1)用于生成向量,a:b,一般要求 a一、matlab 基本操作 Matlab 概率论与数理统计 1. ...概率密度函数 1 (1) 均匀分布:unifpdf(x,a,b)...{X 3}, p1normcdf(5,3,2)- normcdf(2,3,......[A B];rank…

解决MyEclipse JAVA EE无法识别Base64问题

第一步&#xff1a;右击项目选择Build Path,选择Configure Build Path第二步:点击JRE System Library选择右边的Edit第三步&#xff1a;选择Alternate JRE,点击Install JREs第四步&#xff1a;移出原有的MyEclipse自带的 JRE&#xff0c;&#xff08;选中后点击remove&#xff…

JavaFX的响应式设计

使用CSS技术&#xff0c;为您的网站创建响应式设计相对容易。 根据屏幕的大小&#xff0c;您可以使用其他CSS文件和布局。 在JavaFX中&#xff0c;乍一看这似乎有点困难&#xff0c;因为CSS仅负责样式&#xff0c;而不负责布局。 但是&#xff0c;为各个屏幕尺寸使用不同的FXML…

用Vue Node从零开始实现拼多多前后端商城项目 — 记录踩坑之旅(上篇)

前言 本人移动端开发妹子工程师一枚 &#xff0c;因为公司项目需要用到前端的技术(主要是vue)&#xff0c;自己自学了一段时间&#xff0c;最近花了半个月在工作之余的时间终于自己完完整整写下来一整个前后端商城项目(当然是跟了一个线上项目直播班&#xff0c;不要嘲笑我)&am…

python自动补全库_这个库厉害了,自动补全Python代码,节省50%敲码时间

近日&#xff0c;Reddit 上的一篇帖子引起了网友的热议。帖子作者「mlvpj」称&#xff1a;「我们使用深度学习完成了一个简单的项目&#xff0c;可以自动进行 Python 代码补全。」根据介绍&#xff0c;该项目基于 LSTM 模型&#xff0c;训练后&#xff0c;负责对代码的缺失部分…

matlab 小波 cdd,[Matlab] 单导联心电数据的小波(包)消噪及压缩

% 用小波(包)对MitbihCmprTstExample_08730_01(软硬阈值)进行消噪与压缩clear all;clc;close all;disp(用小波(包)对MitbihCmprTstExample_08730_01(软硬阈值)进行消噪和压缩);load MitbihCmprTstExample_08730_01.mat;countlength(sig);xsig(:,1); ysig(:,2); zsig(:,3);TSx(2…