实现消息总线

实现消息总线

  • 发布者: publisher
  • 订阅者: subscriber
  • 事件: event

publisher

EventPublisher:

public interface EventPublisher extends AutoCloseable {

    /**
     * 广播发布事件
     * @param event
     */
    void publish(BootEvent event);

    /**
     * 单个发布
     * @param subscriber
     * @param event
     */
    void notifySubscriber(Subscriber subscriber, BootEvent event);

    /**
     * 添加订阅者
     * @param subscriber
     */
    void addSubscriber(Subscriber subscriber);

    /**
     * 删除订阅者
     * @param subscriber
     */
    void removeSubscriber(Subscriber subscriber);
}

@Slf4j
public class DefaultEventPublisher extends Thread implements EventPublisher {

    private final BlockingQueue<BootEvent> queue;
    private List<Subscriber> list = new ArrayList<>();
    private Map<Class<? extends BootEvent>, List<Subscriber>> map = new ConcurrentHashMap<>();

    private volatile boolean running;

    public DefaultEventPublisher(int queueSize) {
        queue = new ArrayBlockingQueue<>(queueSize);
        setDaemon(true);
        setName("DEFAULT-Publisher-");
        running = true;
        log.info(Thread.currentThread().getName() + " is run..");
        start();
    }

    @Override
    public void publish(BootEvent event) {
        if (!queue.offer(event)) {
            //如果队列已满,则使用调用者线程通知
            log.info("publish event failed, queue size is {}, caller thread runs", queue.size());
            notifyAllSubscribers(event);
        }
    }

    @Override
    public void notifySubscriber(Subscriber subscriber, BootEvent event) {
        if (subscriber.executor() != null) {
            subscriber.executor().submit(() -> subscriber.onEvent(event));
        } else {
            subscriber.onEvent(event);
        }
    }

    @Override
    public void addSubscriber(Subscriber subscriber) {
        list.add(subscriber);
        map.computeIfAbsent(subscriber.supportedType(), clz -> new ArrayList<>());
        map.get(subscriber.supportedType()).add(subscriber);
    }

    @Override
    public void removeSubscriber(Subscriber subscriber) {
        list.remove(subscriber);
        if (map.containsKey(subscriber.supportedType())) {
            map.remove(subscriber.supportedType());
        }
    }

    @Override
    public void run() {
        while (running) {
            try {
                BootEvent event = queue.take();
                notifyAllSubscribers(event);
            } catch (InterruptedException e) {
                log.error("poll event error: ", e);
                Thread.currentThread().interrupt();
            }
        }
    }

    private void notifyAllSubscribers(BootEvent event) {
        for (Subscriber subscriber : list) {
            notifySubscriber(subscriber, event);
        }
    }


    @Override
    public void close() throws Exception {
        running = false;
        queue.clear();
        log.info("publisher close..");
    }
}

PublisherFactory 工厂类:

public interface PublisherFactory {

    EventPublisher create(Class<? extends BootEvent> event, int queueSize);
}

//默认实现
public class DefaultPublisherFactory implements PublisherFactory {

    private Map<Class<? extends BootEvent>, DefaultEventPublisher> map;

    public static DefaultPublisherFactory INSTANCE = new DefaultPublisherFactory();

    private DefaultPublisherFactory() {
        map = new ConcurrentHashMap<>();
    }

    @Override
    public EventPublisher create(Class<? extends BootEvent> event, int queueSize) {
        map.computeIfAbsent(event, e -> {
            DefaultEventPublisher eventPublisher = new DefaultEventPublisher(queueSize);
            return eventPublisher;
        });
        return map.get(event);
    }

    public EventPublisher getPublisher(Class<? extends BootEvent> event) {
        return map.get(event);
    }

    public List<EventPublisher> getEventPublishers() {
        return new ArrayList<>(map.values());
    }


}

订阅者 subscriber

public abstract class Subscriber<E extends BootEvent> {

    public abstract void onEvent(E event);

    public abstract Class<? extends BootEvent> supportedType();

    /**
    * 如果指定了纯种池,则会异步执行
    */
    public ThreadPoolExecutor executor(){
        return null;
    }

}

事件

@Data
public abstract class BootEvent implements Serializable {

    private static AtomicLong SEQ = new AtomicLong(0);

    private Object source;
    private Long timeStamp;
    private Long id;

    public BootEvent(Object source) {
        this.source = source;
        this.timeStamp = System.currentTimeMillis();
        this.id = getSequence();
    }

    private Long getSequence() {
        return SEQ.getAndIncrement();
    }

}

public class LogEvent extends BootEvent {

    @Getter
    private String msg;


    public LogEvent(Object source, String msg) {
        super(source);
        this.msg = msg;
    }
}

通知中心

@Slf4j
public class NotifyBus {

    public static NotifyBus INSTANCE = new NotifyBus();
    private static Integer QUEUE_SIZE = 100;
    private AtomicBoolean CLOSED = new AtomicBoolean(false);
    private DefaultPublisherFactory factory = DefaultPublisherFactory.INSTANCE;

    private NotifyBus() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> NotifyBus.INSTANCE.shutDown()));
    }

    public void setFactory(DefaultPublisherFactory factory) {
        this.factory = factory;
    }

    public void publish(BootEvent event) {
        factory.getPublisher(event.getClass()).publish(event);
    }

    public void addSubscriber(Subscriber subscriber) {
        addSubscriber(subscriber, factory);
    }

    private void addSubscriber(Subscriber subscriber, PublisherFactory factory) {
        EventPublisher eventPublisher = factory.create(subscriber.supportedType(), QUEUE_SIZE);
        eventPublisher.addSubscriber(subscriber);
    }

    public void shutDown() {
        if (!CLOSED.compareAndSet(false, true)) {
            log.error(">>>>> notifyBus already close..");
            return;
        }
        log.info(">>>>> notifyBus close...");
        for (EventPublisher eventPublisher : DefaultPublisherFactory.INSTANCE.getEventPublishers()) {
            try {
                eventPublisher.close();
            } catch (Exception e) {
                log.error("####### notifyBus close error", e);
            }
        }
    }


}

访问

@RestController
public class NotifyBusController {

    @GetMapping("/notify")
    public String notify(@RequestParam String msg) {
        NotifyBus.INSTANCE.publish(new LogEvent(this, msg));
        return "success";
    }
}

结果:

{"source":{},"timeStamp":1684890639183,"id":0,"msg":"hello"}
{"source":{},"timeStamp":1684890642822,"id":1,"msg":"hello"}
notifyBus close...
publisher close..
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值