Spring专题

如何使用Spring3.x事件源码案例

如何使用Spring3.x事件下载源码

创建松耦合的应用程序有很多的概念和技术,事件就是其中之一。事件可以消除许多在你的代码中的依赖关系。在java中Observer接口可以帮助我们实现事件(通过Observer模式)。

想象一下,一个简单的应用程序,这些要求:
 有一些指令,可以有不同的状态
当一个订单交付或推迟状态,我们需要发送电子邮件给客户
第一(但不是最好的)解决方案是在我们的订单模型中直接发送电子邮件,但是,也有一些缺陷:

  1. 这个类不是负责订单发送电子邮件的,违背单一职责。
  2. 如果你遵循领域驱动的原则,订单是一个领域对象,但,电子邮件发件人也许是一种服务(不同于领域服务),所以你不能用它在你的模型中。

订单代码如下

@Configurable
 public 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;
 }
 
@Override
 public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
 this.eventPublisher = applicationEventPublisher;
 }
 
public static enum Status {
 MODIFIABLE,
 CHECKED_OUT,
 POSTPONED,
 DELIVERED,
 CANCELED;
 }
 }

Order类实现org.springframework.context.ApplicationEventPublisherAware接口。这个接口有一个setter方法名称为setApplicationEventPublisher,用来设置ApplicationEventPublisher的。,我们使用这个对象来发布一个事件this.eventPublisher.publishEvent。发布每个事件是继承org.springframework.context.ApplicationEvent

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);
 }
 }

下面是事件的监听者,同时实现邮件发送:

@Service
 public class OrderDeliveredEmailSender implements ApplicationListener,Ordered {
 
@Override
 public 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()));
 }
 
@Override
 public int getOrder() {
 return 100;
 }
 }
 
@Service
 public class OrderPostponedEmailSender implements ApplicationListener {
 
@Override
 public 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()));
 }
 }

onApplicationEvent引发两个对应事件。对于监听发布产品的客户,我们需要创建另一个监听OnOrderDelivered事件。

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

 

在Spring中使用异步事件实现同步事务