Spring Boot集成Guava EventBus并注入Bean

目录

  • 前言
  • 目标
  • 事件总线介绍
    • 概览图
  • 代码实践
    • 基础类
      • IEventBus
      • AbstractSpringEventBus
      • IEventConsumer
    • 业务类
      • 实现事件总线
      • 投递消息
      • 消费者

前言

  • 基于事件总线的方式开发,可以使我们代码更加简洁,而且解耦
  • Guava的EventBus是个轻量级的事件总线,而且事件间可以相互隔离,所以更加灵活多变
  • 本文不讲EventBus的具体功能,只考虑应用场景

目标

  • 在Spring中集成Guava的EventBus,并友好的注入Bean
  • 消费者只需要实现接口,即可接收事件消息
  • 生产者只需要关心消息的生产
  • 事件总线只需要关心生产投递与消息消费的线程、限流等问题

事件总线介绍

概览图

Spring Boot集成Guava EventBus并注入Bean_第1张图片
从上面的事件流图我们可以看到,事件总线是生产者与消费者的枢纽,
我们按照这样的方式,使生产者和消费者解耦,这也是我们为什么要选择事件总线的原因。而且还有重要的是,整个流程被划分成了三块:生成者、消费者、事件枢纽。每一块有只专注自己该干的事。当然这其实就是消息队列,比如其中的限流功能、过滤器功能等等。但我们在轻量级架构使用轻量级的消息队列就好,没必要直接就来Rocket、Rabbit、Kafka。

代码实践

这是我定义的三个基础类,为我们集成到Spring 打下基础
在这里插入图片描述

基础类

IEventBus

顶级事件管理接口,提供消费者订阅、事件投递


/**
 * @author pettyfox
 * @version 1.0
 * @date 2020/9/25 11:57
 */
public interface IEventBus {
     
    /**
     * 发布事件
     * @param event 事件实体
     */
    void post(Object event);

    /**
     * 添加消费者
     * @param obj 消费者对象,默认以class为key
     */
    void addConsumer(Object obj);

    /**
     * 移除消费者
     * @param obj 消费者对象,默认以class为key
     */
    void removeConsumer(Object obj);

    /**
     * 扫描消费者
     * @param packageName 扫描包
     */
    void scanConsumer(String packageName);
}

AbstractSpringEventBus

这个抽象类是Guava EventBus和Spring的桥梁,当然严格来讲是子类实现与Spring的桥梁

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * @author pettyfox
 * @version 1.0
 * @date 2020/9/25 12:23
 */
public abstract class AbstractSpringEventBus implements IEventBus, ApplicationContextAware {
     
    private ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
     
        this.context = applicationContext;
        this.scanConsumer(null);
    }

    @Override
    public void scanConsumer(String packageName) {
     
        context.getBeansOfType(IEventConsumer.class).forEach((k,v)->{
     
            this.addConsumer(v);
        });
    }
}

IEventConsumer

消费者需要实现它


/**
 * @author pettyfox
 * @version 1.0
 * @date 2020/9/25 12:19
 */
public interface IEventConsumer<T> {
     
    /**
     * 消费者事件
     * @param event 事件
     */
    void consumer(T event);
}

业务类

假设我们现在对用户相关行事件管理

实现事件总线


import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.SubscriberExceptionContext;
import com.google.common.eventbus.SubscriberExceptionHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 用户事件总线
 * @author pettyfox
 * @version 1.0
 * @date 2020/9/25 12:57
 */
@Component
@Slf4j
public class UserEventBus extends AbstractSpringEventBus implements  SubscriberExceptionHandler {
     
    private final EventBus eventBus;

    public RecognizeEventBus() {
     
    	//异步事件配置线程池
        eventBus = new AsyncEventBus(new ThreadPoolExecutor(1, 10,
                60L, TimeUnit.SECONDS,
                new SynchronousQueue<Runnable>()), this);
    }

    @Override
    public void post(Object event) {
     
        eventBus.post(event);
    }

    @Override
    public void addConsumer(Object obj) {
     
        eventBus.register(obj);
    }

    @Override
    public void removeConsumer(Object obj) {
     
        eventBus.unregister(obj);
    }

    @Override
    public void handleException(Throwable exception, SubscriberExceptionContext context) {
     
        log.error("user event handler exception", exception);
    }
}

投递消息

@Resource 
private UserEventBus bus;
...
	bus.post(xxxEvent)
...

消费者


import com.alibaba.fastjson.JSON;
import com.google.common.eventbus.Subscribe;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * @author pettyfox
 * @version 1.0
 * @date 2020/9/25 13:08
 */
@Component
@Slf4j
public class RecognizeRecordNotify implements IEventConsumer<XxxEvent> {
     

    @Subscribe
    @Override
    public void consumer(XxxEvent event) {
     
        log.info("event:{}", JSON.toJSONString(event));

    }
}

消费者方法需要加@Subscribe

你可能感兴趣的:(#,后端开发,eventbus,guava)