事件驱动设计是一种基于事件触发和响应的系统设计模式,核心是将事件的产生和处理解耦,消息通知中心就是这种模式的典型落地场景。通过事件驱动设计实现的消息通知中心,可以让不同业务模块之间不需要直接依赖,只需要关注自身需要处理的事件即可,大幅降低系统耦合度。
事件驱动设计核心概念
事件驱动设计主要包含三个核心角色:
- 事件源:产生事件的对象,比如用户下单、支付完成等操作都可以作为事件源
- 事件:封装了事件相关信息的载体,包含事件类型、发生时间、关联数据等
- 事件监听器:监听特定事件,在事件触发时执行对应的处理逻辑
消息通知中心的作用就是管理事件的注册、监听和分发,相当于事件驱动体系中的中枢调度模块。
消息通知中心设计思路
我们可以基于观察者模式来实现消息通知中心,核心逻辑如下:
- 定义统一的事件接口,所有业务事件都实现该接口
- 定义事件监听器接口,不同的事件处理逻辑实现该接口
- 消息通知中心维护一个事件类型到监听器列表的映射关系
- 提供监听器注册、注销方法,以及事件发布方法
- 当事件发布时,通知中心根据事件类型找到所有对应的监听器,依次触发处理逻辑
完整Java代码实现
1. 定义事件接口
所有业务事件都需要实现该接口,封装事件的基本信息:
// 事件接口,所有自定义事件都需要实现该接口
public interface Event {
// 获取事件类型
String getEventType();
// 获取事件发生时间
long getOccurTime();
// 获取事件携带的数据
Object getData();
}
2. 定义具体业务事件
这里以用户注册成功事件为例,实现Event接口:
// 用户注册成功事件
public class UserRegisterEvent implements Event {
// 事件类型常量
public static final String EVENT_TYPE = "USER_REGISTER";
// 事件发生时间
private final long occurTime;
// 事件携带的用户信息
private final String userName;
public UserRegisterEvent(String userName) {
this.occurTime = System.currentTimeMillis();
this.userName = userName;
}
@Override
public String getEventType() {
return EVENT_TYPE;
}
@Override
public long getOccurTime() {
return occurTime;
}
@Override
public Object getData() {
return userName;
}
}
3. 定义事件监听器接口
监听器用于接收并处理对应的事件:
// 事件监听器接口,所有事件处理器都需要实现该接口
public interface EventListener {
// 处理事件的方法
void onEvent(Event event);
}
4. 实现消息通知中心
消息通知中心负责维护监听器和分发事件:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// 消息通知中心实现类
public class MessageNotificationCenter {
// 存储事件类型对应的监听器列表,key为事件类型,value为监听器集合
private final Map<String, List<EventListener>> listenerMap = new HashMap<>();
// 注册事件监听器,将监听器绑定到指定事件类型
public void registerListener(String eventType, EventListener listener) {
listenerMap.computeIfAbsent(eventType, k -> new ArrayList<>()).add(listener);
}
// 注销事件监听器,从指定事件类型中移除监听器
public void unregisterListener(String eventType, EventListener listener) {
List<EventListener> listeners = listenerMap.get(eventType);
if (listeners != null) {
listeners.remove(listener);
}
}
// 发布事件,通知所有监听该事件类型的监听器
public void publishEvent(Event event) {
String eventType = event.getEventType();
List<EventListener> listeners = listenerMap.get(eventType);
if (listeners == null || listeners.isEmpty()) {
return;
}
// 遍历所有监听器,触发处理逻辑
for (EventListener listener : listeners) {
listener.onEvent(event);
}
}
}
5. 编写测试代码验证功能
我们创建两个监听器分别处理用户注册后的发邮件和发积分逻辑,验证通知中心的工作流程:
public class NotificationTest {
public static void main(String[] args) {
// 创建消息通知中心实例
MessageNotificationCenter center = new MessageNotificationCenter();
// 注册发送欢迎邮件的监听器
center.registerListener(UserRegisterEvent.EVENT_TYPE, new EventListener() {
@Override
public void onEvent(Event event) {
String userName = (String) event.getData();
System.out.println("给用户" + userName + "发送注册欢迎邮件,事件时间:" + event.getOccurTime());
}
});
// 注册赠送新用户积分的监听器
center.registerListener(UserRegisterEvent.EVENT_TYPE, new EventListener() {
@Override
public void onEvent(Event event) {
String userName = (String) event.getData();
System.out.println("给用户" + userName + "赠送500新用户积分,事件时间:" + event.getOccurTime());
}
});
// 模拟用户注册,发布用户注册事件
UserRegisterEvent registerEvent = new UserRegisterEvent("张三");
center.publishEvent(registerEvent);
}
}
代码运行结果说明
执行测试代码后,控制台会输出如下内容:
给用户张三发送注册欢迎邮件,事件时间:1698765432100 给用户张三赠送500新用户积分,事件时间:1698765432100
可以看到,当发布用户注册事件后,两个注册的监听器都成功接收到了事件并执行了对应逻辑,说明消息通知中心的功能正常运行。
扩展优化方向
上述实现是基础的同步消息通知中心,实际业务中可以根据需求扩展:
- 支持异步事件处理,避免事件处理逻辑阻塞事件发布线程
- 增加事件优先级,让高优先级的监听器优先处理事件
- 支持事件持久化,防止事件丢失
- 增加监听器异常处理机制,避免单个监听器异常影响其他监听器执行
通过这种基于事件驱动设计的消息通知中心实现,我们可以让业务模块之间的依赖降到最低,后续新增业务只需要新增对应的事件和监听器即可,不需要修改原有代码,符合开闭原则。