javascript
spring 4.3.x_如何在Spring 3.x中使用事件
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偵聽器將捕獲OnOrderDelivered和OnOrderPostponed所有事件
在我們的方案中,它可能適合發送電子郵件。 但是我們不使用此模型,而是為它們創建兩個不同的偵聽器。
如您所見,它們的代碼非常簡單
@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
翻譯自: 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中使用事件的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我的世界电脑版石斧(我的世界电脑版石斧伤
- 下一篇: 使用Spring开发Java RESTf