EventBus源碼學習筆記(一)

EventBus 深刻學習一

EventBus是一個消息總線,以觀察者模式實現,用於簡化程序的組件、線程通訊,能夠輕易切換線程、開闢線程; 傳統上,Java的進程內事件分發都是經過發佈者和訂閱者之間的顯式註冊實現的。設計EventBus就是爲了取代這種顯示註冊方式,使組件間有了更好的解耦。EventBus不是通用型的發佈-訂閱實現,不適用於進程間通訊java

開始以前,咱們能夠先想一下,什麼東西是發佈-訂閱模型,若是要讓咱們本身設計一個發佈-訂閱模型的框架,要怎麼處理android

舉一個小例子,談一下個人理解框架

有一個存錢罐,長輩向裏面放錢(1毛,5毛,1元,5元,10元,20元,50元,100元), 晚輩從裏面取錢;與現實有點不一樣的是,每一個長輩只能投相同面額的錢,晚輩只能獲取相同面額的錢
假設小紅,小明,小剛三我的是取10元錢的,如今張三放了10元錢, 而後主動把這10元錢給這三我的,無論他們去幹嗎(與現實不一樣的是,張三隻防了10元錢,可是小紅,小明,小剛都拿到了這10元錢)

接本的業務流程以下:異步

  • 三個角色,發佈消息者(長輩),存儲消息的管道(存錢罐子),訂閱者(晚輩);
  • 發佈者將發送消息到消息管道
  • 管道則將消息推送給訂閱者

設計:源碼分析

  • 發佈者: 任何發佈消息的人
  • 消息管道: 鏈接發佈者和訂閱者的橋樑,主要有兩個功能,一是接受發佈者發佈的消息;而是將消息推送給訂閱者
    • 維護一個訂閱者關係(消息->訂閱者), 所以須要開放給訂閱者一個註冊的接口
    • 接受發佈者發送消息, 所以須要開放給發佈者一個發佈消息的接口
    • 推送消息給訂閱者, (這裏調用訂閱者提供的消息接受回調方法,實現消息推送)
  • 訂閱者: 每一個訂閱者,關注並處理一種消息類型,
    • 想成爲一個訂閱者,先到消息管道這裏註冊,(告知消費信息的類型以及接受消息的回調方法)
    • 接受消息的回調方法(即接受消息後執行業務邏輯的主體)

post


使用

使用很是簡單, 建立一個 EventBus 實例, 訂閱方,調用 EventBus.register() 方法註冊, 消息發佈方,調用eventBus.post(event); 來發布消息, 則訂閱類中,添加 @subscribe 註解的方法將會接受到這條消息學習

實例以下:ui

/**
 * 發送的消息
 */
@ToString
@Getter
@Setter
public class AuditEvent {

    /**
     * 審覈人
     */
    private String auditUser;


    /**
     * 審覈記錄
     */
    private String record;


    /**
     * 審覈結果
     */
    private AuditEventEnum auditResultEnum;


    public enum AuditEventEnum {

        ACCEPT,

        REJECT,

        RETRY;

    }
}

訂閱者this

/**
 * 初審 & 複審的監聽器
 * <p/>
 * Created by yihui on 2017/3/1.
 */
@Component
public class AuditEventListener {

    private static final Logger logger = LoggerFactory.getLogger(AuditEventListener.class);


    /**
     * 註冊事件
     */
    @PostConstruct
    public void init() {
        ActionEventBus.register(this);
    }


    /**
     * 審覈完成後,會發送一條消息
     * <p/>
     * 1. 經過審覈
     * 2. 拒絕審覈
     * 3. 從新審覈
     * <p/>
     * 根據消息, 作出不一樣的action
     *
     * @param args
     */
    @Subscribe
    public void invoke(AuditEvent args) {

        if (args.getAuditResultEnum() == AuditEvent.AuditEventEnum.ACCEPT) {
            System.out.println(1111);
            logger.info("審覈經過!!!! {}", args.getRecord());
        } else if (args.getAuditResultEnum() == AuditEvent.AuditEventEnum.REJECT) {
            System.out.println(2222);
            logger.info("審覈拒絕!!!! {}", args.getRecord());
        } else {
            logger.info("從新審覈!!!! {}", args.getRecord());
        }

    }
}

EventBus管理工廠google

public class ActionEventBus {

    private final static EventBus eventBus = new EventBus();


    public static void post(Object event) {
        eventBus.post(event);
    }

    public static void register(Object handler) {
        eventBus.register(handler);
    }

    public static void unregister(Object handler) {
        eventBus.unregister(handler);
    }

}

發佈消息

@Test
public void testAudit() {
   AuditEvent auditEvent = new AuditEvent();
   auditEvent.setAuditResultEnum(AuditEvent.AuditEventEnum.ACCEPT);
   auditEvent.setAuditUser("1hui");
   auditEvent.setRecord("test1");

   // 發佈一條成功的消息
   ActionEventBus.post(auditEvent);



   auditEvent.setAuditResultEnum(AuditEvent.AuditEventEnum.REJECT);
   auditEvent.setAuditUser("2hui");
   auditEvent.setRecord("test2");
   // 發佈一條拒絕的消息
   ActionEventBus.post(auditEvent);




   BuyEvent buyEvent = new BuyEvent();
   buyEvent.setBuyerUser("3hui");
   buyEvent.setCount(1);
   buyEvent.setTotalPrice(10000L);
   buyEvent.setItem("java book");
   buyEvent.setBuyEventEnum(BuyEventEnum.PAY);
   ActionEventBus.post(buyEvent);
   System.out.println("over");
}

分析

說明,咱們先拿google的 Guava中的 EventBus 來做爲研究對象; 後續會對比下android平臺上使用很是多的greenrobot/EventBus

從上面的使用能夠簡單的看出EventBus的設計思路基本上仍是 消息-訂閱的模子,可是設計很是巧妙

從訂閱者角度來看,首先是要註冊,沒什麼好說的,關鍵點就在於接受消息的處理方法上

- 添加一個註解,指定消息接收類型(即參數類型), 就能夠接受這類消息
- 基於上面的方法,一個訂閱者,能夠實現訂閱多個不一樣的消息源

消息發佈方來看,直接調用 EventBus.post() 就算是發佈消息,使用起來超級簡單

其中 EventBus 做爲溝通的橋樑,也就是上面咱們說的‘儲錢罐’, 若是希冀實現異步的消息處理,則直接用AsyncEventBus 便可

從上面的使用來看,極大的簡化了使用的流程,簡直不能更easy了; 惟一的遺憾是,從上面的描述中,發現使用異步的話,還得改用AsyncEventBus 有點麻煩,若是能直接再 @subscribe 註解中添加個標識,表示是否使用異步消費就完美了


前期準備

在真正進入源碼分析以前,咱們先作些準備工做,瞭解下基本的術語和背景

1. 事件監聽者(Listeners)

即咱們上面的訂閱者,最終接受事件,並執行響應的業務邏輯的主體

在EventBus實例上調用EventBus.register(Object)方法註冊事件監聽者;須要注意的是請保證事件生產者和監聽者共享相同的EventBus實例

2. 事件生產者(Producers)

發送事件的主體,經過把事件傳遞給 EventBus.post(Object)方法。異步分發能夠直接用EventBus的子類AsyncEventBus

3. 術語

術語 說明
事件 能夠向事件總線發佈的對象
訂閱 向事件總線註冊監聽者以接受事件的行爲
監聽者 提供一個處理方法,但願接受和處理事件的對象
處理方法 監聽者提供的公共方法,事件總線使用該方法向監聽者發送事件;該方法應該用Subscribe註解
發佈消息 經過事件總線向全部匹配的監聽者提供事件
相關文章
相關標籤/搜索