guava中的事件總線(觀察者模式的應用)

觀察者模式:定義對象間一種一對多的依賴關係,使得每當一個對象改變狀態,所有依賴它的對象都會得到通知並自動更新。

Guava框架中的EventBus(事件總線)是對觀察者模式的一種實現。
EventBus是在單體架構內實現的松耦合的絕佳方式,通過它可以很簡潔的實現事件註冊監聽和消費。
在這裏插入圖片描述
Guava框架中提供了EventBus(同步)和AsyncEventBus(異步,繼承於EventBus)兩種時間總線:
1.單線程同步事件消費
2.多線程異步事件消費

Guava默認訂閱者的消費方法不具有併發能力,如果你的消費方法具有併發能力,可以使用@AllowConcurrentEvents註解,用來標記當前訂閱者是線程安全的,支持併發接收事件消息。

訂閱方法(被@Subscribe修飾的方法)的參數類型與事件發佈者一致時,將會接收到消息並消費。若事件發佈者post的某個事件沒有被訂閱,那麼改時間將會被修飾爲DeadEvent,並被對應的DeadEvent訂閱者接收處理。


import com.google.common.eventbus.*;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName: EventBusTest
 * @Description: TODO
 * @Author: RuiXin Yu
 * @Date: 2019/9/19 20:59
 */
public class EventBusTest {
    private static class Event1 {
        @Override
        public String toString() {
            return "事件1";
        }
    }
    private static class Event2 {
        @Override
        public String toString() {
            return "事件2";
        }
    }
    private static class EventX {
        @Override
        public String toString() {
            return "事件X";
        }
    }
    private static class EventListener {
        @Subscribe
        @AllowConcurrentEvents
        public void onEvent(Event1 event1) throws InterruptedException {
            String name = Thread.currentThread().getName();
            System.out.println(name + " sleep 一會兒");
            Thread.sleep(1000);
            System.out.println(name + "===訂閱事件1,接收到:" + event1);
        }
        @Subscribe
        public void onEvent(Event2 event2) throws InterruptedException {
            String name = Thread.currentThread().getName();
            System.out.println(name + " sleep 一會兒");
            Thread.sleep(1000);
            System.out.println(name + "===訂閱事件2,接收到:" + event2);
        }
        @Subscribe
        public void onEvent(DeadEvent deadEvent) throws InterruptedException {
            String name = Thread.currentThread().getName();
            Thread.sleep(10*1000);
            System.out.println(name + "===訂閱錯誤的事件,接收到:" + deadEvent);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        String name = Thread.currentThread().getName();
        EventBus eb = new EventBus();
        eb.register(new EventListener());
        System.out.println(name + "----------發送事件X---------");
        eb.post(new EventX());
        System.out.println(name + "----------發送事件1----並行接收-----");
        ExecutorService threadPool = Executors.newCachedThreadPool();
        eb = new AsyncEventBus(threadPool);
        eb.register(new EventListener());
        for (int i = 0; i < 10; i++) {
            eb.post(new Event1());
        }
        Thread.sleep(2000);
        System.out.println(name + "----------發送事件2----串行接收-----");
        for (int i = 0; i < 10; i++) {
            eb.post(new Event2());
        }
        Thread.sleep(2000);
        threadPool.shutdown();
    }
}

控制檯打印

main----------發送事件X---------
main===訂閱錯誤的事件,接收到:DeadEvent{source=EventBus{default}, event=事件X}
main----------發送事件1---------
pool-1-thread-1 sleep 一會兒
pool-1-thread-2 sleep 一會兒
pool-1-thread-3 sleep 一會兒
pool-1-thread-4 sleep 一會兒
pool-1-thread-5 sleep 一會兒
pool-1-thread-6 sleep 一會兒
pool-1-thread-7 sleep 一會兒
pool-1-thread-8 sleep 一會兒
pool-1-thread-9 sleep 一會兒
pool-1-thread-10 sleep 一會兒
pool-1-thread-1===訂閱事件1,接收到:事件1
pool-1-thread-2===訂閱事件1,接收到:事件1
pool-1-thread-3===訂閱事件1,接收到:事件1
pool-1-thread-4===訂閱事件1,接收到:事件1
pool-1-thread-5===訂閱事件1,接收到:事件1
pool-1-thread-7===訂閱事件1,接收到:事件1
pool-1-thread-6===訂閱事件1,接收到:事件1
pool-1-thread-8===訂閱事件1,接收到:事件1
pool-1-thread-9===訂閱事件1,接收到:事件1
pool-1-thread-10===訂閱事件1,接收到:事件1
main----------發送事件2---------
pool-1-thread-9 sleep 一會兒
pool-1-thread-9===訂閱事件2,接收到:事件2
pool-1-thread-2 sleep 一會兒
pool-1-thread-2===訂閱事件2,接收到:事件2
pool-1-thread-5 sleep 一會兒
pool-1-thread-5===訂閱事件2,接收到:事件2
pool-1-thread-3 sleep 一會兒
pool-1-thread-3===訂閱事件2,接收到:事件2
pool-1-thread-4 sleep 一會兒
pool-1-thread-4===訂閱事件2,接收到:事件2
pool-1-thread-1 sleep 一會兒
pool-1-thread-1===訂閱事件2,接收到:事件2
pool-1-thread-7 sleep 一會兒
pool-1-thread-7===訂閱事件2,接收到:事件2
pool-1-thread-6 sleep 一會兒
pool-1-thread-6===訂閱事件2,接收到:事件2
pool-1-thread-8 sleep 一會兒
pool-1-thread-8===訂閱事件2,接收到:事件2
pool-1-thread-10 sleep 一會兒
pool-1-thread-10===訂閱事件2,接收到:事件2

import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * @ClassName: EventBusTest
 * @Description: TODO
 * @Author: Yu RuiXin
 * @Date: 2020/1/20 17:27
 */
public class EventBusTest {


    static void sendPost(EventBus eb, String appId, String bizCode, String bizSubCode,String data) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        EventTypeEnum eventTypeEnum = EventTypeEnum.valueOf(appId, bizCode, bizSubCode);
        Constructor constructor = eventTypeEnum.eventClass.getConstructor(String.class);
        Object event = constructor.newInstance(data);
        eb.post(event);
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
        EventBus eb = new EventBus();
        eb.register(new EventListener());
        sendPost(eb,"1","11","111","這是數據啊");
        sendPost(eb,"x","xx","xxx","這是數據啊");
        sendPost(eb,"2","22","222","這是數據啊");
    }


    enum EventTypeEnum {
        EVENT1("1", "11", "111", Event1.class),
        EVENT2("2", "22", "222", Event2.class),
        EVENT3("x", "xx", "xxx", EventX.class),
        ;

        private String appId;
        private String bizCode;
        private String bizSubCode;
        private Class eventClass;

        EventTypeEnum(String appId, String bizCode, String bizSubCode, Class eventClass) {
            this.appId = appId;
            this.bizCode = bizCode;
            this.bizSubCode = bizSubCode;
            this.eventClass = eventClass;
        }

        public static EventTypeEnum valueOf(String appId, String bizCode, String bizSubCode) {
            for (EventTypeEnum t : EventTypeEnum.values()) {
                if (t.appId.equals(appId) && t.bizCode.equals(bizCode) && t.bizSubCode.equals(bizSubCode)) {
                    return t;
                }
            }
            return null;
        }
    }

    @Data
    @AllArgsConstructor
    static class Event {
        String data;
    }

    static class Event1 extends Event {
        public Event1(String data) {
            super(data);
        }
    }

    static class Event2 extends Event {
        public Event2(String data) {
            super(data);
        }
    }

    static class EventX extends Event {
        public EventX(String data) {
            super(data);
        }
    }

    private static class EventListener {
        @Subscribe
        public void onEvent(Event1 event1) {
            System.out.println("事件1:"+event1.getData());
        }
        @Subscribe
        public void onEvent(Event2 event2) {
            System.out.println("事件2:"+event2.getData());
        }
        @Subscribe
        public void onEvent(EventX eventX) {
            System.out.println("事件3:"+eventX.getData());
        }
    }

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章