Google Guava的EventBus(事件总线)基本使用

        EventBusGoogle.Guava提供的消息发布-订阅组件,采用的是观察者模式(生产/消费者编程模型),

实现了多组件之间通信的解耦合,事件产生方和事件消费方实现解耦分离,提升了通信的简洁性。

相比MQ它更加轻量,易用,但一般只用于进程内部的通信,不能像MQ一样用于分布式系统的服务与服务之间的通信。

       EventBus包含3大核心部分:Event事件, Publisher事件发布者,Subscriber事件订阅者。

       下面介绍一下它的使用方法:

一、在pom.xml中引入guava的依赖

<dependency>

     <groupId>com.google.guava</groupId>

     <artifactId>guava</artifactId>

     <version>19.0</version>

</dependency>

二、自定义事件类

     事件是EventBus之间相互通信的基本单位,一个Event可以是任何类型。

为了规范,我们一般在自定义事件类时会以Event作为类名的结尾,例:

import lombok.Data;

/**
 * 自定义一个添加告警消息的事件
 */
@Data
public class AddAlertMsgEvent {

    private String calcNodeCode;

    private String orgCode;

}

三、事件监听

     事件监听即事件的订阅者,就是接收事件的一方,这些订阅者需要在自己的方法上,添加@Subscribe注解声明自己为事件订阅者。

    一般@Subscribe可以配合@AllowConcurrentEvents注解一起使用,这个注解是用来标识当前订阅者是线程安全的,可以减少同步开销。

    例:

/**
 * 事件监听器
 */
@Component
public class EventListener {

    @Subscribe
    @AllowConcurrentEvents
    public void addAlertMsg(AddAlertMsgEvent event) {
        //在这里可以做你需要的处理
    }

}

   监听类里面可以写多个监听的方法,记得在方法上添加@Subscribe注解。

四、定义一个工具类用来获取EventBus和发送事件

   事件发布者,就是发送事件到EventBus事件总线的一方,事件发布者调用Post()方法,将事件发给EventBus。

   例:

import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;

import java.util.concurrent.*;

public class EventBusUtil {

    private static EventBus eventBus;
    private static AsyncEventBus asyncEventBus;
    private static Executor executor = new ThreadPoolExecutor(1, 10, 60,
            TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(100000), Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());

        /**
         * 异步事件单例模式
         * @return
         */
    private static synchronized AsyncEventBus getAsyncEventBus() {
        if(asyncEventBus == null){
            asyncEventBus = new AsyncEventBus(executor);
        }
        return asyncEventBus;
    }

    /**
     * 同步事件单例模式
     * @return
     */
    private static synchronized EventBus getEventBus() {
        if(eventBus == null) {
            eventBus = new EventBus();
        }
        return eventBus;
    }

    /**
     * 同步发送事件
     * @param event
     */
    public static void post(Object event) {
        getEventBus().post(event);
    }

    /**
     * 异步发送事件
     * @param event
     */
    public static void asyncPost(Object event) {
        getAsyncEventBus().post(event);
    }

    /**
     * 监听器注册
     * @param object
     */
    public static void register(Object object) {
        getEventBus().register(object);
        getAsyncEventBus().register(object);
    }

}

五、监听器(订阅者)注册

      只有将监听器所在的类,注册到EventBus中,EventBus才能扫描到这个订阅者。

      在项目启动的时候调用EventBusUtil.register(eventListener)即可,下面以我使用的SpringBoot项目为例:

@Order(1)
@Slf4j
@Component
@Configuration
public class ApplicationListenerImpl implements ApplicationListener<ApplicationReadyEvent> {

    @Resource
    private EventListener eventListener;

    @Override
    public void onApplicationEvent(ApplicationReadyEvent event) {
        log.info("ApplicationReadyEvent init restTemplate.");
        try {
            //监听器注册
            EventBusUtil.register(eventListener);
        } catch (Exception e) {
            log.error("初始化配置失败!", e);
        }
        log.info("ApplicationReadyEvent init restTemplates finished.");
    }

}

六、使用EventBus

    至此你就可以愉快的使用EventBus了,下面举个简单的例子:

//使用Eventbus添加告警信息
AddAlertMsgEvent addAlertMsgEvent = new AddAlertMsgEvent();
addAlertMsgEvent.setOrgCode(orgInfoEntity.getOrgCode());
addAlertMsgEvent.setCalcNodeCode(orgInfoEntity.getCalcNodeCode());
//发送异步事件
EventBusUtil.asyncPost(addAlertMsgEvent);

七、拓展:EventBus和AsyncEventBus使用区别

EventBus:同步事件总线

1.同步执行,事件发送方在发出事件之后,会等待所有的事件消费方执行完毕后,才会回来继续执行自己后面的代码。

2.事件发送方和事件消费方会在同一个线程中执行,消费方的执行线程取决于发送方。

3.同一个事件的多个订阅者,在接收到事件的顺序上面有不同。谁先注册到EventBus的,谁先执行,如果是在同一个类中的两个订阅者一起被注册到EventBus的情况,收到事件的顺序跟方法名有关。

AsyncEventBus:异步事件总线

1.异步执行,事件发送方异步发出事件,不会等待事件消费方是否收到,直接执行自己后面的代码。

2.在定义AsyncEventBus时,构造函数中会传入一个线程池。事件消费方收到异步事件时,消费方会从线程池中获取一个新的线程来执行自己的任务。

3.同一个事件的多个订阅者,它们的注册顺序跟接收到事件的顺序上没有任何联系,都会同时收到事件,并且都是在新的线程中,异步并发的执行自己的任务。


 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值