spring 4.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

spring 4.3.x

spring 4.3.x_如何在Spring 3.x中使用事件相关推荐

  1. spring vertx_如何在Spring设置Vertx

    spring vertx by Rick Lee 李瑞克(Rick Lee) 如何在Spring设置Vertx (How to set up Vertx in Spring) Spring is pr ...

  2. 如何在 Spring 生态中玩转 RocketMQ?

    作者 | 通融.洛夜 来源 | 阿里巴巴云原生公众号 RocketMQ 作为业务消息的首选,在消息和流处理领域被广泛应用.而微服务生态 Spring 框架也是业务开发中最受欢迎的框架,两者的完美契合使 ...

  3. 如何在spring中读取properties配置文件里面的信息

    如何在spring中读取properties配置文件里面的信息 <!-- 正文开始 --> 一般来说.我们会将一些配置的信息放在.properties文件中. 然后使用${}将配置文件中的 ...

  4. 如何在Spring boot中修改默认端口

    文章目录 介绍 使用Property文件 在程序中指定 使用命令行参数 值生效的顺序 如何在Spring boot中修改默认端口 介绍 Spring boot为应用程序提供了很多属性的默认值.但是有时 ...

  5. 如何在Spring Boot应用程序中使用配置文件

    你好朋友, 在本教程中,我们将学习如何在Spring Boot应用程序中使用配置文件. 我们将在本教程中讨论以下几点: 1.什么是Spring Boot Profile,为什么我们需要分析 2.如何使 ...

  6. 如何在Spring Boot App中集成H2数据库

    你好朋友, 在本教程中,我们将尝试探索如何在Spring Boot应用程序中与H2数据库集成. 在进行检查之前,让我们了解有关H2数据库的一些基础知识,如下所述,然后我们将讨论H2数据库与Spring ...

  7. java 自定义xml_6.1 如何在spring中自定义xml标签

    dubbo自定义了很多xml标签,例如,那么这些自定义标签是怎么与spring结合起来的呢?我们先看一个简单的例子. 一 编写模型类 1 packagecom.hulk.testdubbo.model ...

  8. 如何在Spring生态中玩转RocketMQ?

    简介: RocketMQ作为业务消息的首选,在消息和流处理领域被广泛应用.而微服务生态Spring框架也是业务开发中最受欢迎的框架,两者的完美契合使得RocketMQ成为Spring Messagin ...

  9. Java访问静态常量_Java如何在Spring EL中访问静态方法或常量?

    在这个例子中,您将学习如何使用Spring Expression Language访问类范围的方法或常量.要访问类范围的方法或常量T(),例如,您将需要使用Spring EL的运算符T(java.la ...

最新文章

  1. Android中使用Adapter(适配器)给RecycleView设置数据源
  2. 23V3有这种C语言表达式吗,数据结构(C语言版第2版_李云清)习题答案2012-12.doc
  3. centos 无法连接网络
  4. C#使用Json.NET解析Json
  5. Linux系统开机自动加载驱动module
  6. BNUOJ 1207 滑雪
  7. sublime 插件安装;sublime的 babel、sublime-jsfmt插件
  8. Oracle单个数据文件超过32G后需要扩容
  9. DotNet Core 2.0部署后外网IP访问
  10. input自适应_一种Dynamic ReLU:自适应参数化ReLU激活函数(调参记录13)
  11. 结对-贪吃蛇-开发过程
  12. xstream java_XStream将java转化成xml的简单使用
  13. python求解简单加密问题,实现对输入的密文加密
  14. 三网融合:不给安全营造“盗梦空间”
  15. RTCM3.1/3.2
  16. Excel删除自定义模板
  17. 地震 matlab,MATLAB在地震信号处理中的应用实例.docx
  18. 【转】为什么火线有电压,零线没有电压呢?
  19. 手淘推出“店铺二楼”
  20. 几行CSS让你的页面立体起来

热门文章

  1. 5、oracle下数据完整性约束
  2. 使用Docker 实现微服务并搭建博客,一文全掌握
  3. 分布式事务解决方案——柔性事务与服务模式
  4. Object.keys方法拿到对象的key值
  5. Js如何判断undefined和null
  6. Android中ImageView的scaleType 属性说明。
  7. repo-话说软件详细设计工具
  8. Multi-catch parameters are not allowed for source level below 1.7 解决方法
  9. xml json 比较_JSON和XML:它们如何比较?
  10. jax-rs/jersey_JAX-RS 2.1的Jersey客户端依赖性