SpringBoot 事件发布&订阅实现通用业务处理

80 阅读2分钟

前言

多个业务操作(发布课表、直播信息变更、讲义信息变更)需要执行一批相同逻辑处理(删除缓存),可以借助Spring自带的事件发布&订阅机制。 ps:懒得用 mq -_-

定义事件

@Getter
@Setter
public class CRChangeEvent extends ApplicationEvent {

    /**
     * 课表id集合
     */
    private List<Integer> curriculumIds;

    /**
     * 是否发布课表
     */
    private Boolean isCurriculumPublish;

    public CRChangeEvent(Object source, List<Integer> curriculumIds) {
        super(source);
        this.curriculumIds = curriculumIds;
        this.isCurriculumPublish = Boolean.FALSE;
    }

    public CRChangeEvent(Object source, Integer curriculumId) {
        super(source);
        this.curriculumIds = Collections.singletonList(curriculumId);
        this.isCurriculumPublish = Boolean.FALSE;
    }

    public CRChangeEvent(Object source, Integer curriculumId, Boolean isCurriculumPublish) {
        super(source);
        this.curriculumIds = Collections.singletonList(curriculumId);
        this.isCurriculumPublish = isCurriculumPublish;
    }
}

定义监听器

/**
 * 课表资源变更事件监听
 *
 */
@Component
@Slf4j
public class CRChangeListener {

    @Resource
    private ArkRedisClient arkRedisClient;

    /**
     * 默认是同步的,添加 @Async 注解代表异步处理
     * @param changeEvent 事件对象
     */
    @EventListener
    @Async
    public void onProcessCRChange(CRChangeEvent changeEvent) {

        log.info("课表资源变更监听开始清理缓存 changeEvent={}", JSON.toJSONString(changeEvent));
        List<Integer> curriculumIds = changeEvent.getCurriculumIds();
        if (CollectionUtils.isEmpty(curriculumIds)) {
            log.info("课表资源变更事件监听,curriculumIds is null");
            return;
        }

        curriculumIds.forEach(curriculumId -> {
            arkRedisClient.del(RedisKeyEnum.CURRICULUM_LECTURE_NODE_LIST.getKey() + 1 + ":" + curriculumId);
        });

    }
}

发布事件

1. 启动类获取 AC

/**
 * 在某些特殊的情况下,Bean需要实现某个功能,但该功能必须借助于Spring容器才能实现,此时就必须让该Bean先获取Spring容器,然后借助于Spring容器实现该功能。
 * 为了让Bean获取它所在的Spring容器,可以让该Bean实现ApplicationContextAware接口。
 * ApplicationContextAware 通过它Spring容器会自动把上下文环境对象调用ApplicationContextAware接口中的setApplicationContext方法。
 * 在ApplicationContextAware的实现类中,就可以通过这个上下文环境对象得到Spring容器中的Bean。
 * 看到*Aware就知道是干什么的了,就是属性注入的,
 * 但是这个ApplicationContextAware的不同地方在于:实现了这个接口的bean,当spring容器初始化的时候,会自动的将ApplicationContext注入进来。
 * Create By IntelliJ IDEA
 *
 */
public class ProductServiceApplication implements ApplicationContextAware {

    public static ApplicationContext AC;

    public static void main(String[] args) {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
        SpringApplication.run(ProductServiceApplication.class, args);
    }
    @Override
    public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
        AC = applicationContext;
    }

}

2. 发布事件

import static com.iqihang.ark.product.ProductServiceApplication.AC;
...
 AC.publishEvent(new CRChangeEvent(this, id, true));

参考

www.cnblogs.com/toutou/p/Ap… juejin.cn/post/684490…