005:基于观察者模式设计异步多渠道群发框架
1 观察者模式课程内容的引入
课程内容
- 观察者模式基本的observer概念
- 观察者模式在实际开发中的应用场景
- 如何基于观察者模式设计多渠道群发框架
- ApplicationListener事件监听原理
2 观察者模式介绍
观察者基本概念
当一个对象发生改变的时候可以通知给其他所有的对象
观察者应用场景
- zk临时节点监听(当zk临时节点发生变化,会通知给所有客户端)
- 分布式配置中心 nacos、config、携程Apollo刷新配置文件
- 多渠道群发
addOrder(){
// 1.向数据库中插入订单数据
// 2.发送短信代码
// 3.发送邮件代码
// 4.发送微信代码
}
==》观察者模式一行代码封装
3 观察者模式类图结构的分析
4 定义观察者模式的接口
public interface Observer {
void sendMsg(JSONObject jsonObject);
}
@Component
@Slf4j
public class SmsObserver implements Observer {
@Override
public void sendMsg(JSONObject jsonObject) {
log.info("使用观察者发送短信");
}
}
@Component
@Slf4j
public class EmailObserver implements Observer {
@Override
public void sendMsg(JSONObject jsonObject) {
log.info("使用观察者发送邮件");
}
}
@Component
public class MayiktSubject {
private List<Observer> listObserver = new ArrayList<>();
private ExecutorService executorService;
public MayiktSubject() {
executorService = Executors.newFixedThreadPool(10);
}
/**
* 新增Observer
*
* @param Observer
*/
public void addObserver(Observer Observer) {
listObserver.add(Observer);
}
/**
* 通知给所有观察者
*
* @param jsonObject
*/
public void notifyObServer(JSONObject jsonObject) {
for (Observer obServer : listObserver) {
// 单独开启线程异步通知
executorService.execute(() -> obServer.sendMsg(jsonObject));
}
}
}
5 项目启动注册读观察者(自动注册)
@Component
public class StartService implements ApplicationRunner, ApplicationContextAware {
@Autowired
private SmsObserver smsObserver;
@Autowired
private EmailObserver emailObserver;
@Autowired
private MayiktSubject mayiktSubject;
private ApplicationContext applicationContext;
// 当SpringBoot启动成功之后,再注册SmsObserver和EmailObserver
@Override
public void run(ApplicationArguments args) throws Exception {
// mayiktSubject.addObserver(smsObserver);
// mayiktSubject.addObserver(emailObserver);
// 使用java反射机制获取Observer下所有子类自动注册到集合中
/**
* 自动注册观察者
* 1. 使用Spring获取该Observer下有哪些bean对象
* 2. 直接添加到集合中
*/
// 根据接口类型返回相应的所有bean
Map<String, Observer> map = applicationContext.getBeansOfType(Observer.class);
for (String key : map.keySet()) {
Observer Observer = map.get(key);
mayiktSubject.addObserver(Observer);
}
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
6 测试手写观察者模式
@RestController
@Slf4j
public class OrderService {
@Autowired
private MayiktSubject mayiktSubject;
@RequestMapping("/addOrder")
public String addOrder() {
log.info("1.调用数据库下单订单代码:");
JSONObject jsonObject = new JSONObject();
jsonObject.put("sms", "1865891111");
jsonObject.put("email", "644064779@qq.com");
mayiktSubject.notifyObServer(jsonObject);
return "success";
}
}
运行结果:
7 使用Spring事件监听实现观察者
定义消息实体类
@Data
public class UserMessageEntity extends ApplicationEvent {
private String email;
private String phone;
private String userId;
public UserMessageEntity(Object source) {
super(source);
}
public UserMessageEntity(Object source, String email, String phone) {
super(source);
this.email = email;
this.phone = phone;
}
@Override
public String toString() {
return "email:" + email + ",phone:" + phone;
}
}
定义事件通知
@Component
@Slf4j
public class EmailListener implements ApplicationListener<UserMessageEntity> {
/**
* 监听的方法
*
* @param event
*/
@Override
public void onApplicationEvent(UserMessageEntity event) {
log.info("使用SpringBoot观察者发送邮件:" + event.getEmail());
}
}
@Component
@Slf4j
public class SmsListener implements ApplicationListener<UserMessageEntity> {
/**
* 监听的方法
*
* @param event
*/
@Override
public void onApplicationEvent(UserMessageEntity event) {
log.info("使用SpringBoot观察者发送短信:" + event.getPhone());
}
}
发布事件
@RestController
@Slf4j
public class OrderService {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@RequestMapping("/addOrder2")
public String addOrder2() {
log.info("1.调用数据库下单订单代码:");
UserMessageEntity userMessageEntity = new UserMessageEntity(this, "644064779@qq.com", "1865891111");
applicationEventPublisher.publishEvent(userMessageEntity);
return "success";
}
}
运行结果:
源码下载地址(mayikt_designPattern_5.zip):
链接:https://pan.baidu.com/s/1wWKZN1MbXICZVW1Vxtwe6A
提取码:fire