Event Bus设计模式

EventBus是消息中间件的设计思想,在此设计中有三个非常重要的角色(Bus、Registry、Dispatcher),Bus主要负责提供给外部使用的操作方法;Registry注册表用来整理记录所有注册在EventBus上的Subscriber;Dispatcher主要负责对Subscriber消息进行推送(用反射的方式执行方法),考虑到程序的灵活性,Dispatcher方法也提供了Executor的多态方式。

示例代码如下:

java 复制代码
public interface Bus {
void register(Object subscriber);
void unregister(Object subscriber);
void post(Object event);
void post(Object event,String topic);
void close();
String getBusName();
}
java 复制代码
import java.lang.reflect.Method;

public interface EventContext {
String getSource();
Object getSubscriber();
Method getSubscribe();
Object getEvent();
}
java 复制代码
public interface EventExceptionHandler {
void handle(Throwable cause,EventContext context);
}
java 复制代码
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(METHOD)
public @interface Subscribe {
String topic() default "default-topic";
}
java 复制代码
public class Subscriber {
private final Object subscribeObject;
private final Object subscribeMethod;
private boolean disable=false;

public Subscriber(Object subscribeObject,Object subscribeMethod) {
this.subscribeObject=subscribeObject;
this.subscribeMethod=subscribeMethod;
}

public Object getSubscribeObject() {
return subscribeObject;
}

public Object getSubscribeMethod() {
return subscribeMethod;
}

public boolean isDisable() {
return disable;
}

public void setDisable(boolean disable) {
this.disable = disable;
}
}
java 复制代码
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;


class Registry {
private final ConcurrentHashMap<String,ConcurrentLinkedQueue<Subscriber>> subscriberContainer=new ConcurrentHashMap<>();

private List<Method> getSubscribeMethods(Object subscriber){
final List<Method> methods=new ArrayList<>();
Class<?> type=subscriber.getClass();
while(type!=null) {
Method[] declaredMethods=type.getDeclaredMethods();
Arrays.stream(declaredMethods).filter(m->m.isAnnotationPresent(Subscribe.class)
&&m.getParameterCount()==1
&&m.getModifiers()==Modifier.PUBLIC)
.forEach(methods::add);
type=type.getSuperclass();
}
return methods;
}

private void tierSubscriber(Object subscriber,Method method) {
final Subscribe subscribe=method.getDeclaredAnnotation(Subscribe.class);
String topic=subscribe.topic();
this.subscriberContainer.computeIfAbsent(topic, key->new ConcurrentLinkedQueue());
this.subscriberContainer.get(topic).add(new Subscriber(subscriber,method));
}

public void bind(Object subscriber) {
List<Method> subscribeMethods=getSubscribeMethods(subscriber);
subscribeMethods.forEach(m->tierSubscriber(subscriber,m));
}

public void unbind(Object subscriber) {
this.subscriberContainer.forEach((key,queue)->queue.forEach(s->{
if(s.getSubscribeObject()==subscriber) {
s.setDisable(true);
}
}));
}

public ConcurrentLinkedQueue<Subscriber> scanScriber(String topic) {
return this.subscriberContainer.get(topic);
}
}
java 复制代码
import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

public class Dispatcher {
private final Executor executorService;
private final EventExceptionHandler exceptionHandler;
public static final Executor SEQ_EXECUTOR_SERVICE=SeqExecutorService.INSTANCE;
public static final Executor PER_THREAD_EXECUTOR_SERVICE=PerThreadExecutorService.INSTANCE;

private Dispatcher(Executor executorService,EventExceptionHandler handler) {
this.executorService=executorService;
this.exceptionHandler=handler;
}

private void realInvokeSubscribe(Subscriber subscriber,Object event,Bus bus) {
Method method=(Method) subscriber.getSubscribeMethod();
Object object=subscriber.getSubscribeObject();
this.executorService.execute(()->{
try {
method.invoke(object, event);
} catch (Exception e) {
if(null!=exceptionHandler) {
exceptionHandler.handle(e, new BaseEventContext(bus.getBusName(),subscriber,event));
}
e.printStackTrace();
}
});
}

public void dispatch(Bus bus, Registry registry,Object event, String topic) {
ConcurrentLinkedQueue<Subscriber> subscribers=registry.scanScriber(topic);
if(null==subscribers) {
if(exceptionHandler!=null) {
exceptionHandler.handle(new IllegalArgumentException("The topic "+topic+" not bind yet"),
new BaseEventContext(bus.getBusName(),null,event));
}
return ;
}
subscribers.stream().filter(subscriber->!subscriber.isDisable())
.filter(subscriber->{
Method method=(Method) subscriber.getSubscribeMethod();
Class<?> aClass=method.getParameterTypes()[0];
return (aClass.isAssignableFrom(event.getClass()));
}).forEach(subscriber->this.realInvokeSubscribe(subscriber, event, bus));
}

public void close() {
if(this.executorService instanceof ExecutorService) {
((ExecutorService)this.executorService).shutdown();
}
}

static Dispatcher newDispatcher(EventExceptionHandler handler,Executor executor) {
return new Dispatcher(executor,handler);
}

static Dispatcher seqDispatcher(EventExceptionHandler handler) {
return new Dispatcher(SEQ_EXECUTOR_SERVICE,handler);
}

static Dispatcher perThreadDispatcher(EventExceptionHandler handler) {
return new Dispatcher(PER_THREAD_EXECUTOR_SERVICE,handler);
}

private static class SeqExecutorService implements Executor{
private final static SeqExecutorService INSTANCE=new SeqExecutorService();
@Override
public void execute(Runnable command) {
command.run();
}
}

private static class PerThreadExecutorService implements Executor{
private final static PerThreadExecutorService INSTANCE=new PerThreadExecutorService();
@Override
public void execute(Runnable command) {
new Thread(command).start();
}
}

private static class BaseEventContext implements EventContext{
private final String eventBusName;
private final Subscriber subscriber;
private final Object event;
private BaseEventContext(String eventBusName,Subscriber subscriber,Object event) {
this.eventBusName=eventBusName;
this.subscriber=subscriber;
this.event=event;
}
@Override
public String getSource() {
return this.eventBusName;
}

@Override
public Object getSubscriber() {
return this.subscriber!=null?subscriber.getSubscribeObject():null;
}

@Override
public Method getSubscribe() {
return this.subscriber==null?(Method)subscriber.getSubscribeMethod():null;
}

@Override
public Object getEvent() {
return this.event;
}
}
}
java 复制代码
import java.util.concurrent.Executor;

public class EventBus implements Bus{
private final Registry resitry=new Registry();
private String busName;
private static final String DEFAULT_BUS_NAME="default";
private static final String DEFAULT_TOPIC="default-topic";
private final Dispatcher dispatcher;

public EventBus() {
this(DEFAULT_BUS_NAME,null,Dispatcher.SEQ_EXECUTOR_SERVICE);
}

public EventBus(String busName) {
this(busName,null,Dispatcher.SEQ_EXECUTOR_SERVICE);
}

EventBus(String busName,EventExceptionHandler handler,Executor executor){
this.busName=busName;
this.dispatcher=Dispatcher.newDispatcher(handler, executor);
}

public EventBus(EventExceptionHandler exceptionHandler) {
this(DEFAULT_BUS_NAME,exceptionHandler,Dispatcher.SEQ_EXECUTOR_SERVICE);
}

@Override
public void register(Object subscriber) {
this.resitry.bind(subscriber);
}

@Override
public void unregister(Object subscriber) {
this.resitry.unbind(subscriber);
}

@Override
public void post(Object event) {
this.post(event,DEFAULT_TOPIC);
}

@Override
public void post(Object event, String topic) {
this.dispatcher.dispatch(this, resitry, event, topic);
}

@Override
public void close() {
this.dispatcher.close();
}

@Override
public String getBusName() {
return this.busName;
}

}
java 复制代码
import java.util.concurrent.ThreadPoolExecutor;

public class AsyncEventBus extends EventBus{

AsyncEventBus(String busName,EventExceptionHandler handler,ThreadPoolExecutor executor){
super(busName,handler,executor);
}

public AsyncEventBus(String busName,ThreadPoolExecutor threadPoolExecutor) {
this(busName, null, threadPoolExecutor);
}

public AsyncEventBus(ThreadPoolExecutor executor) {
this("default-async",null,executor);
}

public AsyncEventBus(EventExceptionHandler handler,ThreadPoolExecutor executor) {
this("default-async",handler,executor);
}
}
java 复制代码
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public class SimpleScriberTest {

@Subscribe
public void methodA(String message) {
System.out.println("==SimpleSubscriber==methodA=="+message);
}

@Subscribe(topic="test")
public void methodB(String message) {
System.out.println("==SimpleSubscriber==methodB=="+message);
}

public static void main(String[] args) {
//Bus bus=new EventBus("TestBus");
Bus bus=new AsyncEventBus("TestBus",(ThreadPoolExecutor)Executors.newFixedThreadPool(10));
bus.register(new SimpleScriberTest());
bus.post("Hello");
System.out.println("__________________");
bus.post("Hello", "test");
}

}
相关推荐
tianchang13 分钟前
SSR 深度解析:从原理到实践的完整指南
前端·vue.js·设计模式
咖啡啡不加糖20 分钟前
RabbitMQ 消息队列:从入门到Spring Boot实战
java·spring boot·rabbitmq
玩代码27 分钟前
Java线程池原理概述
java·开发语言·线程池
NE_STOP30 分钟前
SpringBoot--如何给项目添加配置属性及读取属性
java
水果里面有苹果32 分钟前
20-C#构造函数--虚方法
java·前端·c#
%d%d236 分钟前
python 在运行时没有加载修改后的版本
java·服务器·python
金銀銅鐵42 分钟前
[Kotlin] 单例对象是如何实现的?
java·kotlin
泰勒疯狂展开43 分钟前
Java研学-MongoDB(三)
java·开发语言·mongodb
zzywxc7871 小时前
AI技术通过提示词工程(Prompt Engineering)正在深度重塑职场生态和行业格局,这种变革不仅体现在效率提升,更在重构人机协作模式。
java·大数据·开发语言·人工智能·spring·重构·prompt
饕餮争锋1 小时前
设计模式笔记_创建型_建造者模式
笔记·设计模式·建造者模式