Event Bus 设计模式
Event Bus 中文翻译为消息中间件 主要解决进程之间消息异步处理。例如当一个订单支付后,会触发库存计算,物流调度计算,报表统计等操作。那么可以将订单支付完成通知放在消息中间件,这样注册在消息中间件的其他系统就可以顺利地接收到订单通知,执行各自的业务逻辑。
Event Bus 重要角色
- Bus 中间件 提供给外部使用的操作方法
- Registry 注册表 整理记录所有注册到EventBus的消息接收者(Subscriber)和主题(topic)的关系。
- Dispatcher 消息分发处理器 通过注册表对应关系将消息分发给各个消息接收器
- Subscriber 消息接收者 接收消息并处理自身业务逻辑。
Bus中间件接口
/**
* 对外提供几种使用方法
* 例如 post方法用来发送Event(消息)
* register方法用来注册Subscriber(消息接收者)
*/
public interface Bus {
/**
* 将某个对象注册到Bus上,从此之后该类型成为 Subscriber
*/
void register(Object subscriber);
/**
* 将某个对象从Bus上取消注册,之后就不会再接收来自Bus的消息
*/
void unregister(Object subscriber);
/**
* 提交Event 到指定的 topic
*/
void post(Object event,String topic);
/**
* 提交Event 到默认的 topic
*/
void post(Object event);
/**
* 关闭bus
*/
void close();
/**
* 获取Bus的标志名称
*/
String getBusName();
}
Registry 注册表
/**
* 注册表类
*/
class Registry {
// 储存Subscriber(消息接收者)集合和topic之间的关系集合
private final ConcurrentHashMap<String, ConcurrentLinkedDeque<Subscriber>> subscriberContainer = new ConcurrentHashMap<>();
// 绑定消息接收者
public void bind(Object subscriber){
//获取 消息接收者的添加@Subscrib注解方法集合 和消息接收者进行绑定
List<Method> subscribeMethod = getSubscribeMethod(subscriber);
subscribeMethod.forEach(m -> tierSubscriber(subscriber,m));
}
// 消息接收者解绑
public void unbind(Object subscriber){
// 解绑为了提高速度 只对Subscriber进行失效操作
subscriberContainer.forEach((key,queue) ->
queue.forEach(s -> {
if (s.getSubscribeObject() == subscriber){
s.setDisable(true);
}
}));
}
// 根据topic 主题获取对应消息接收者队列 方法参数添加final 防止变量在方法体中被改变
public ConcurrentLinkedDeque<Subscriber> scanSubscriber(final String topic){
return subscriberContainer.get(topic);
}
/**
* 将绑定对象封装成Subscriber 注册到subscriberContainer的topic对应集合中
*/
private void tierSubscriber(Object subscriber, Method method) {
// 获取@Subscribe注解信息
final Subscribe subscribe = method.getDeclaredAnnotation(Subscribe.class);
String topic = subscribe.topic();
// 当topic没有 就新建一个 有就添加到对应的集合中
subscriberContainer.computeIfAbsent(topic, key-> new ConcurrentLinkedDeque<>());
// 再将消息接收者添加到对应的 topic的集合中
subscriberContainer.get(topic).add(new Subscriber(subscriber,method));
}
/**
* 查找绑定对象的方法是否添加 @Subscrib注解
* @param subscriber
* @return
*/
private List<Method> getSubscribeMethod(Object subscriber) {
final List<Method> methods = new ArrayList<>();
Class<?> temp = subscriber.getClass();
// 不断的获取当前类和父类的所有添加 @Subscrib注解的方法
while (temp != null){
// 获取当前类的所以方法
Method[] declaredMethods = temp.getDeclaredMethods();
// 只有public 方法 && 有一个入参 && 被@Subscrib注解 的方法才满足 是回调方法
Arrays.stream(declaredMethods)
.filter(m -> m.isAnnotationPresent(Subscribe.class)
&& m.getParameterCount() == 1
&& m.getModifiers() == Modifier.PUBLIC)
.forEach(methods::add);
// 取父类消息
temp = temp.getSuperclass();
}
return methods;
}
}
Dispatcher 分发处理器
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
/**
* 将订单通知消息(Event) 推送到每个注册到topic上的消息接收者(Subscriber)上
*/
public class Dispatcher {
// 线程池
private final Executor executorService;
// 异常回调接口
private final EventExceptionHandler exceptionHandler;
// 顺序执行的ExecutorService 线程池 静态内部类实现单例
public static final Executor SEQ_EXECUTOR_SERVICE = SeqExecutorService.INSTANCE;
// 每个消息推送都开辟一个线程执行的 线程池 holder方式实现
public static final Executor PRE_THREAD_EXECUTOR_SERVICE = PreThreadExecutorService.INSTANCE;
private Dispatcher(