YMP Online Manual / 事件服务(Event)

事件服务(Event)

事件服务,通过事件的注册、订阅和广播完成事件消息的处理,目的是为了减少代码侵入,降低模块之间的业务耦合度,事件消息采用队列存储,采用多线程接口回调实现消息及消息上下文对象的传输,支持同步和异步两种处理模式;

框架事件初始化配置参数
#-------------------------------------
# 框架事件初始化参数
#-------------------------------------

# 默认事件触发模式(不区分大小写),取值范围:NORMAL-同步执行,ASYNC-异步执行,默认为ASYNC
ymp.event.default_mode=

# 事件管理提供者接口实现,默认为net.ymate.platform.core.event.impl.DefaultEventProvider
ymp.event.provider_class=

# 事件线程池初始化大小,默认为Runtime.getRuntime().availableProcessors()
ymp.event.thread_pool_size=

# 事件配置扩展参数,xxx表示自定义参数名称,vvv表示参数值
ymp.event.params.xxx=vvv
YMP核心事件对象
  • ApplicationEvent:框架事件

    APPLICATION_INITED - 框架初始化
    APPLICATION_DESTROYED - 框架销毁
  • ModuleEvent:模块事件

    MODULE_INITED - 模块初始化
    MODULE_DESTROYED - 模块销毁

:以上只是YMP框架核心中包含的事件对象,其它模块中包含的事件对象将在其相应的文档描述中阐述;

事件的订阅
  • 方式一:通过代码手动完成事件的订阅

    public static void main(String[] args) throws Exception {
        YMP.get().init();
        try {
            // 订阅模块事件
            YMP.get().getEvents().registerListener(ModuleEvent.class, new IEventListener<ModuleEvent>() {
                @Override
                public boolean handle(ModuleEvent context) {
                    switch (context.getEventName()) {
                        case MODULE_INITED:
                            // 注意:这段代码是不会被执行的,因为在我们进行事件订阅时,模块的初始化动作已经完成
                            System.out.println("Inited :" + context.getSource().getName());
                            break;
                        case MODULE_DESTROYED:
                            System.out.println("Destroyed :" + context.getSource().getName());
                            break;
                    }
                    return false;
                }
            });
        } finally {
            YMP.get().destroy();
        }
    }
  • 方式二:通过@EventRegister注解和IEventRegister接口实现事件的订阅

    // 首先创建事件注册类,通过实现IEventRegister接口完成事件的订阅
    // 通过@EventRegister注解,该类将在YMP框架初始化时被自动加载
    @EventRegister
    public class DemoEventRegister implements IEventRegister {
        public void register(Events events) throws Exception {
            // 订阅模块事件
            events.registerListener(ModuleEvent.class, new IEventListener<ModuleEvent>() {
                @Override
                public boolean handle(ModuleEvent context) {
                    switch (context.getEventName()) {
                        case MODULE_INITED:
                            System.out.println("Inited :" + context.getSource().getName());
                            break;
                        case MODULE_DESTROYED:
                            System.out.println("Destroyed :" + context.getSource().getName());
                            break;
                    }
                    return false;
                }
            });
            //
            // ... 还可以添加更多的事件订阅代码
        }
    }
    
    // 框架启动测试
    public static void main(String[] args) throws Exception {
        YMP.get().init();
        try {
            // Do Nothing...
        } finally {
            YMP.get().destroy();
        }
    }
自定义事件

YMP的事件对象必须实现IEvent接口的同时需要继承EventContext对象,下面的代码就是一个自定义事件对象:

  • 创建自定义事件对象

    public class DemoEvent extends EventContext<Object, DemoEvent.EVENT> implements IEvent {
    
        public enum EVENT {
            CUSTOM_EVENT_ONE, CUSTOM_EVENT_TWO
        }
    
        public DemoEvent(Object owner, Class<? extends IEvent> eventClass, EVENT eventName) {
            super(owner, eventClass, eventName);
        }
    }

    说明:EventContext的注解中的第一个参数代表事件源对象类型,第二个参数是指定用于事件监听事件名称的枚举类型;

  • 注册自定义事件

    YMP.get().getEvents().registerEvent(DemoEvent.class);
  • 订阅自定义事件

    事件订阅(或监听)需实现IEventListener接口,该接口的handle方法返回值在异步触发模式下将影响事件监听队列是否终止执行,同步触发模式下请忽略此返回值;

    YMP.get().getEvents().registerListener(DemoEvent.class, new IEventListener<DemoEvent>() {
    
        public boolean handle(DemoEvent context) {
            switch (context.getEventName()) {
                case CUSTOM_EVENT_ONE:
                    System.out.println("CUSTOM_EVENT_ONE");
                    break;
                case CUSTOM_EVENT_TWO:
                    System.out.println("CUSTOM_EVENT_TWO");
                    break;
            }
            return false;
        }
    });

    当然,也可以通过@EventRegister注解和IEventRegister接口实现自定义事件的订阅;

    :当某个事件被触发后,订阅(或监听)该事件的接口被回调执行的顺序是不能被保证的;

  • 触发自定义事件

    // 采用默认模式触发事件
    YMP.get().getEvents().fireEvent(new DemoEvent(YMP.get(), DemoEvent.class, DemoEvent.EVENT.CUSTOM_EVENT_ONE));
    
    // 采用异步模式触发事件
    YMP.get().getEvents().fireEvent(Events.MODE.ASYNC, new DemoEvent(YMP.get(), DemoEvent.class, DemoEvent.EVENT.CUSTOM_EVENT_TWO));
  • 示例测试代码:

    public static void main(String[] args) throws Exception {
        YMP.get().init();
        try {
            // 注册自定义事件对象
            YMP.get().getEvents().registerEvent(DemoEvent.class);
            // 注册自定义事件监听
            YMP.get().getEvents().registerListener(DemoEvent.class, new IEventListener<DemoEvent>() {
    
                public boolean handle(DemoEvent context) {
                    switch (context.getEventName()) {
                        case CUSTOM_EVENT_ONE:
                            System.out.println("CUSTOM_EVENT_ONE");
                            break;
                        case CUSTOM_EVENT_TWO:
                            System.out.println("CUSTOM_EVENT_TWO");
                            break;
                    }
                    return false;
                }
            });
            // 采用默认模式触发事件
            YMP.get().getEvents().fireEvent(new DemoEvent(YMP.get(), DemoEvent.class, DemoEvent.EVENT.CUSTOM_EVENT_ONE));
            // 采用异步模式触发事件
            YMP.get().getEvents().fireEvent(Events.MODE.ASYNC, new DemoEvent(YMP.get(), DemoEvent.class, DemoEvent.EVENT.CUSTOM_EVENT_TWO));
        } finally {
            YMP.get().destroy();
        }
    }