CDI 事件機(jī)制是整個(gè)精髓所在,有點(diǎn)類似于觀察者模式。
定義一個(gè)Room類型 的一個(gè)添加房間的事件類型,名字并不重要,重要的是類型
@Inject
@Add
Event<Room> roomAddEvent;
頁(yè)面上點(diǎn)擊按鈕觸發(fā)事件,事件生產(chǎn)者通過(guò)調(diào)用fire()方法,并傳遞"事件對(duì)象"從而激活事件處理. 。
/**
* 入住房間
*
* @return 這里利用JSF的特性:返回空字符串或者null表示刷新當(dāng)前頁(yè)面
*/
public String checkIn(Room room) {
roomAddEvent.fire(room);
return null;
}
這個(gè)時(shí)候@Observers修飾的訂閱者就可以接收事件,并執(zhí)行任務(wù),并通過(guò)@Add這個(gè)qualifter來(lái)區(qū)別唯一事件類型。
public void onAddRoom(@Observes @Add Room room){
log.info("add room:{}.",room);
room.setStatus(RoomStatus.AVAILABLE);
rooms.add(room);
}
動(dòng)態(tài)注入事件
這樣如果有多個(gè)事件就不需要為每個(gè)事件都定義一個(gè)Qualifter了。
roomAddEvent.select(new AnnotationLiteral<Add>(){}).fire(Room);
定義一個(gè)有條件的觀察者
默認(rèn)情況下,在當(dāng)前上下文如果沒(méi)有一個(gè)觀察者的實(shí)例,容器將為事件實(shí)例化觀察者.但我們希望傳遞給觀察者的實(shí)例是已經(jīng)存在于上下文中的觀察者.指定一個(gè)有條件的觀察者的方式是在@Observes注釋上添加receive = IF_EXISTS
public void refreshOnDocumentUpdate(@Observes(receive = IF_EXISTS) @Updated Document d) { ... }
為Qualifter設(shè)置成員變量
可以通過(guò)@Qualifter的value值傳遞信息給observer.
@Qualifier
@Target({METHOD, FIELD, PARAMETER, TYPE})
@Retention(RUNTIME)
public @interface Role {
RoleType value();
}
訂閱事件時(shí)候調(diào)用
public void adminLoggedIn(@Observes @Role(ADMIN) LoggedIn event) { ... }
多重qualifiers
@Inject @Blog Event<Document> blogEvent;
...
if (document.isBlog()) blogEvent.select(newAnnotationLiteral<Updated>(){}).fire(
下面的觀察者都可以得到通知
public void afterBlogUpdate(@Observes @Updated @Blog Document document) { ... }
public void afterDocumentUpdate(@Observes @Updated Document document) { ... }
public void onAnyBlogEvent(@Observes @Blog Document document) { ... }
public void onAnyDocumentEvent(@Observes Document document) { ... }}}
但是下面這個(gè)方法不會(huì)得到通知,因?yàn)锧Personal沒(méi)有包含在事件發(fā)生處
public void afterPersonalBlogUpdate(@Observes @Updated @Personal @Blog Document document) { ... }
事物處理的Event
1. IN_PROGRESS --- observers被立即通知 (default)
2. AFTER_SUCCESS --- 在事務(wù)成功完成后,observers會(huì)被通知.
3. AFTER_FAILURE --- 在事務(wù)完成失敗后,observers會(huì)被通知.
4. AFTER_COMPLETION --- observers在交易完成后的階段被調(diào)用
5. BEFORE_COMPLETION --- observers在交易完成前階段被調(diào)用
比如下面這個(gè)只有事物成功后才會(huì)被通知。
public void refreshCategoryTree(@Observes(during = AFTER_SUCCESS) CategoryUpdateEvent event) { ... }
參考:
https://my.oschina.net/zhaoqian/blog/265207
示例代碼:
https://github.com/liuqinyi/weld-tutorial
https://github.com/liuqinyi/quickstart.git