CDI组件技术(四)—— 难点event

CDI 事件机制是整个精髓所在,有点类似于观察者模式
定义一个Room类型 的一个添加房间的事件类型,名字并不重要,重要的是类型

    @Inject
    @Add
    Event<Room> roomAddEvent;

页面上点击按钮触发事件,事件生产者通过调用fire()方法,并传递"事件对象"从而激活事件处理. 。

    /**
     * 入住房间
     *
     * @return 这里利用JSF的特性:返回空字符串或者null表示刷新当前页面
     */
    public String checkIn(Room room) {
        roomAddEvent.fire(room);
        return null;
    }

这个时候@Observers修饰的订阅者就可以接收事件,并执行任务,并通过@Add这个qualifter来区别唯一事件类型。

    public void onAddRoom(@Observes @Add Room room){
        log.info("add room:{}.",room);
        room.setStatus(RoomStatus.AVAILABLE);
        rooms.add(room);
    }

动态注入事件

这样如果有多个事件就不需要为每个事件都定义一个Qualifter了。

roomAddEvent.select(new AnnotationLiteral<Add>(){}).fire(Room);

定义一个有条件的观察者

默认情况下,在当前上下文如果没有一个观察者的实例,容器将为事件实例化观察者.但我们希望传递给观察者的实例是已经存在于上下文中的观察者.指定一个有条件的观察者的方式是在@Observes注释上添加receive = IF_EXISTS

public void refreshOnDocumentUpdate(@Observes(receive = IF_EXISTS) @Updated Document d) { ... }

为Qualifter设置成员变量

可以通过@Qualifter的value值传递信息给observer.

@Qualifier
@Target({METHOD, FIELD, PARAMETER, TYPE})
@Retention(RUNTIME)
public @interface Role { 
    RoleType value();
}

订阅事件时候调用

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) { ... }}}

但是下面这个方法不会得到通知,因为@Personal没有包含在事件发生处

public void afterPersonalBlogUpdate(@Observes @Updated @Personal @Blog Document document) { ... }

事物处理的Event

1. IN_PROGRESS --- observers被立即通知 (default)
2. AFTER_SUCCESS --- 在事务成功完成后,observers会被通知.
3. AFTER_FAILURE --- 在事务完成失败后,observers会被通知.
4. AFTER_COMPLETION --- observers在交易完成后的阶段被调用
5. BEFORE_COMPLETION --- observers在交易完成前阶段被调用

比如下面这个只有事物成功后才会被通知。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,908评论 18 139
  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,209评论 30 471
  • 什么是Run Loops RunLoops是与线程相关联的基础部分,一个Run Loop就是事件处理循环,他是用来...
    傻傻小萝卜阅读 994评论 0 5
  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 13,910评论 0 15
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,208评论 25 708