使用spring的观察者模式(事件监听)

以实际案例出发,商城商家发货后,会通过短信和邮件方式通知买家。但后期可能会增加微信通知和qq通知,想到设计模式中的观察者模式,于是结合spring,整理一下代码流程

1.定义事件 (继承ApplicationEvent抽象类 )



import org.springframework.context.ApplicationEvent;

import java.util.Map;

/**
 * @Description 发货事件(使用观察者模式实现发货后的事件处理,如邮件通知、短信提醒等)
 * @Author: yanxh<br>
 * @Date 2019-12-11 10:39<br>
 * @Version 1.0<br>
 */
public class OrderDeliveryEvent extends ApplicationEvent {

    private Map<String, Object> params;

    public OrderDeliveryEvent(Object source, Map<String, Object> params) {
        super(source);
        this.params = params;
    }

    public Map<String, Object> getParams() {
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }
}

2.定义事件监听者 (实现ApplicationListener接口


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * @Description 订单发货邮件监听
 * @Author: yanxh<br>
 * @Date 2019-12-11 10:44<br>
 * @Version 1.0<br>
 */
@Component
public class OrderDeliveryEmailListener implements ApplicationListener<OrderDeliveryEvent> {

    @Autowired
    private RestTemplate restTemplate;

    /** 线程 */
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    /**
     * @Description todo
     * @Author: yanxh<br>
     * @Date 2019/12/11 13:22<br>
     * @Version 1.0<br>
     */
    @Override
    public void onApplicationEvent(OrderDeliveryEvent event) {
        // 发货后传递的数据
        Map<String, Object> params = event.getParams();
        // 下面为处理邮件发送的逻辑。。因只做观察者说明,所以邮件发送的具体业务代码暂不透漏了
        Long orderId = Long.valueOf(String.valueOf(params.get("orderId")));
        Long billId = Long.valueOf(String.valueOf(params.get("billId")));
        // 放于异步线程中处理
        taskExecutor.execute(new SendMailToOrg(orderId, billId, restTemplate));
    }
}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * @Description 订单发货短信监听
 * @Author: yanxh<br>
 * @Date 2019-12-11 10:44<br>
 * @Version 1.0<br>
 */
@Component
public class OrderDeliveryMessageListener implements ApplicationListener<OrderDeliveryEvent> {

    @Autowired
    private RestTemplate restTemplate;

    /** 线程 */
    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public void onApplicationEvent(OrderDeliveryEvent event) {
        // 发短信的业务逻辑,异步线程处理
        taskExecutor.execute(new OrderDeliveryMessage(event.getParams(), restTemplate));
    }

}

多个观察者在spring启动时会自动绑定到接口中泛型代表的事件中

 3.触发事件

发货逻辑。。。

// 事件传递的信息
Map<String, Object> params = new HashMap<String, Object>(0);
ApplicationEvent orderDeliveryEvent = new OrderDeliveryEvent(this, params);
// 调用父容器发布事件
ContextLoader.getCurrentWebApplicationContext().publishEvent(orderDeliveryEvent);

注意事项

在web项目中如果同时集成了spring和springMVC的话,上下文中会存在两个容器,
即spring的applicationContext.xml的父容器和springMVC的applicationContext-mvc.xml的子容器
通过applicationContext发送通知的时候,事件会被两个容器发布
所以要通过获取父容器的方式去发布事件,避免事件重复发送
原创文章 148 获赞 258 访问量 11万+

猜你喜欢

转载自blog.csdn.net/yxh13521338301/article/details/103491047