Skip to content

事件与监听

事件与监听是 niucloud 进行代码解耦的基础,是 niucloud 区别与其他系统一个很重要的技术点。通过事件与监听可以将系统的业务进行分离,比如支付,存储,订单业务等。下面针对具体的几个案例说明一下事件与监听的执行过程。后期可以与微服务设计中消息相结合

事件与监听架构

事件命名 event,监听命名 listener,包括系统定义的事件和插件定义的事件。具体文件夹如下:

核心组件

  1. 事件基类 (Event)

    • 继承自 Spring 的 ApplicationEvent

    • 包含站点 ID、应用列表、授权控制等核心属性

    • 提供事件发布的基础结构

  2. 事件发布工具 (EventAndSubscribeOfPublisher)

    • 提供多种事件发布方法

    • 支持同步回调和异步发布

    • 支持站点授权控制

  3. 事件定义器 (EventDefiner)

    • 定义事件的数据结构

    • 定义事件结果的数据结构

    • 提供事件处理的抽象方法

  4. 事件监听器 (CallbackListener)

    • 实现事件的具体处理逻辑

    • 继承自事件定义器

    • 提供回调结果

命名规范

  • 事件定义:业务名称+EventDefiner

  • 事件类:业务名称+Event

  • 事件结果类:业务名称+EventResult

  • 事件监听器:业务名称+Listener

事件定义与发布

事件定义示例

事件定义采用 抽象类+内部静态事件类+内部静态结果类 的结构:

java
@EqualsAndHashCode(callSuper = false)
@Data
public abstract class MallShopGoodsListEventDefiner extends CallbackListener<MallShopGoodsListEventDefiner.MallShopGoodsListEvent> {

    @Override
    public abstract MallShopGoodsListEventResult handleCallback(MallShopGoodsListEvent event);

    /**
     * 事件结果定义
     */
    @EqualsAndHashCode(callSuper = true)
    @Data
    public static class MallShopGoodsListEventResult extends EventResult {
        //店铺街商品列表
        private List<MallGoodsListVo> goods;
        //首页-甄选好店商品列表
        private List<MallGoodsListVo> goodsList;
    }

    /**
     * 事件主题定义
     */
    @EqualsAndHashCode(callSuper = true)
    @Data
    public static class MallShopGoodsListEvent extends Event {
        private Integer num = 3; // 默认返回3个商品
    }
}

事件发布方式

使用 EventAndSubscribeOfPublisher 工具类发布事件:

java
// 1. 发布所有应用的事件(异步)
EventAndSubscribeOfPublisher.publishAll(event);

// 2. 根据站点ID发布事件(支持授权控制)
EventAndSubscribeOfPublisher.publishBySiteId(event);

// 3. 发布事件并获取回调结果(同步)
List<EventResult> results = EventAndSubscribeOfPublisher.publishAndCallback(event);

// 4. 根据站点ID发布事件并获取回调结果(同步)
List<EventResult> results = EventAndSubscribeOfPublisher.publishAndCallbackBySite(event);

实际使用示例

SiteShopServiceImpl 中的使用:

java
// 发布店铺商品列表事件,获取商品数据
MallShopGoodsListEventDefiner.MallShopGoodsListEvent event = new MallShopGoodsListEventDefiner.MallShopGoodsListEvent();
event.setSiteId(site.getSiteId());
event.setNum(2); // 只返回2个商品
List<MallShopGoodsListEventDefiner.MallShopGoodsListEventResult> results = EventAndSubscribeOfPublisher.publishAndCallback(event);

// 处理回调结果
if (results != null && !results.isEmpty()) {
    MallShopGoodsListEventDefiner.MallShopGoodsListEventResult result = results.get(0);
    if (result != null && result.getGoodsList() != null) {
        goodsList = result.getGoodsList();
    }
}

事件监听实现

监听器实现示例

监听器需要继承对应的事件定义器,并实现抽象的 handleCallback 方法:

java
@Component
public class MallShopGoodsListListener extends MallShopGoodsListEventDefiner {

    @Override
    public MallShopGoodsListEventResult handleCallback(MallShopGoodsListEvent event) {
        MallShopGoodsListEventResult result = new MallShopGoodsListEventResult();
        
        // 1. 获取参数
        Integer siteId = event.getSiteId();
        Integer num = event.getNum() != null ? event.getNum() : 3;
        
        // 2. 执行业务逻辑
        List<MallGoodsListVo> goodsList = new ArrayList<>();
        // TODO: 查询店铺商品列表逻辑
        
        // 3. 设置结果
        result.setGoodsList(goodsList);
        
        return result;
    }
}

同步与异步事件

异步事件

  • 使用 publishAllpublishBySiteId 方法

  • 适合不需要立即获取结果的场景,如会员注册后发送通知

  • 执行效率高,不阻塞主线程

同步回调事件

  • 使用 publishAndCallbackpublishAndCallbackBySite 方法

  • 适合需要获取扩展返回数据的场景,如支付方式扩展、营销价格计算

  • 阻塞主线程,等待所有监听器处理完成

基于 MIT 协议发布