在实际开发中,我们经常会需要做一件事:在完成某一个动作之后,需要另外以同步或者异步的方式去通知另外的对象去完成额外的操作,比如:当用户下单成功之后,需要发异步消息到给到邮件系统发邮件(短信)通知用户。(这里就涉及到异步消息的概念)
消息队列是我们用来解决系统与系统之间异步与解耦的极佳实践工具,而在应用内部这个级别上,有时候也会需要这样的异步消息通知机制。

spring提供的事件通知机制是基于在容器内部注册与监听的模式,本质上是Observer模式(观察者模式)。对于不明白观察者模式或者忘记的,可以百度了解一下。其实在jdk中也有对观察者模式做了实现,有兴趣的读者也可以了解一下。事件发布注册早容器中(事件注册中心),由事件注册中心去通知相应的监听器去处理该事件。
实现流程一般为:
1、定义扩展自ApplicationEvent类的事件。
2、定义实现自ApplicationListener接口的监听器。
3、通过上下文环境进行事件发布。
代码如下:
/**
 * 下单事件
 * 
 * @author lennon
 *
 */
public class OrderCreateEvent extends ApplicationEvent{
    private static final long serialVersionUID = 1L;
    
    private String orderSn;
    public OrderCreateEvent(String orderSn) {
        super(SpringContextHolder.getApplicationContext());
        this.orderSn = orderSn;
    }
    public String getOrderSn() {
        return orderSn;
    }
    public void setOrderSn(String orderSn) {
        this.orderSn = orderSn;
    }
}
/**
 * 下单事件监听器
 * 
 * @author lennon
 *
 */
@Component
@Async
public class OrderCreateEventListener implements ApplicationListener<OrderCreateEvent> {
    @Override
    public void onApplicationEvent(OrderCreateEvent orderCreateEvent) {
        // 对下单操作进行处理
        System.out.println("打印订单");
        System.out.println(orderCreateEvent.getOrderSn());
    }
}
/**
 * 下单成功之后发布异步事件
 * 
 * @author lennon
 *
 */
public class OrderCreateEventPublisher {
    
    public void afterCreateOrder() {
        
        // 下单
        OrderCreateEvent orderCreateEvent = new OrderCreateEvent(UUID.randomUUID().toString());
        
        // ....
        // 下单成功
        System.out.println("下单成功之后,异步做一些简单处理");
        
        
        SpringContextHolder.getApplicationContext().publishEvent(orderCreateEvent);
        
        System.out.println("异步之后!");
    }
}
/**
 * 持有spring的上下文对象
 * 
 * @author lennon
 *
 */
@Component
public class SpringContextHolder implements ApplicationContextAware{
    private static ApplicationContext applicationContext = null;  
      
    @Override  
    public void setApplicationContext(ApplicationContext applicationContext)  
            throws BeansException {  
        this.applicationContext = applicationContext;  
    }  
      
    public static Object getBean(String name){  
        return applicationContext.getBean(name);  
    }
    
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
}
总结:
1、异步Event事件与自定义线程实现,到底哪种好?什么时候要用异步事件,什么时候使用线程?
2、什么时候使用异步Event,什么时候使用同步Event?
3、深入了解底层的观察者模式,如何自己写出一套基于发布与订阅的异步Event事件框架?【值得尝试做一下,重复造轮子可以检验自己的能力】
 
  
  
  
 
 
  
 
