SpringBoot - Google EventBus、AsyncEventBus

这篇具有很好参考价值的文章主要介绍了SpringBoot - Google EventBus、AsyncEventBus。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

EventBus 顾名思义,事件总线,是一个轻量级的发布/订阅模式的应用模式,最初设计及应用源与 google guava 库。

相比于各种 MQ 中间件更加简洁、轻量,它可以在单体非分布式的小型应用模块内部使用(即同一个JVM范围)。

我们也可以把它和 MQ 中间件结合起来使用,使用 EventBus 作为当前应用程序接收中间件 MQ 消息的统一入口,然后应用内部基于 EventBus 进行分发订阅,以达到高内聚低耦合的目的(当应用内部需要消费多种不同 MQ 中间件消息时,不需要在当前应用的好多不同代码位置都编写 MQ 消费代码)。

EventBus 整体设计和流程比较简单,由注册、发布和订阅三个要点组成,如下:
SpringBoot - Google EventBus、AsyncEventBus,Spring Boot,Java开发,java,消息订阅消费

注意事项

本文对 google guava 库中的 EventBus 进行实例说明,注意事项要先进行特别说明。

  • EventBus 默认为同步调用,同一个 EventBus 中注册的多个订阅处理,再事件下发后是被总线串行逐个调用的,如果其中一个方法占用事件较长,则同一个 EventBus 中的其他事件处于等待状态,且发送消息事件的代码调用处也是同步调用等待的状态。
  • 同一个 EventBus 对象,不仅仅在同一个 post 调用中串行执行,在多次并发 post 调用时,多个 post 调用之间也是串行等待执行的关系,这个要特别注意,应用不当会导致严重的消息消费处理性能瓶颈问题!

所以推荐使用异步的方式处理,异步处理主要包括 “EventBus 使用线程池统一异步” 和 “订阅消费处理代码自己使用线程异步” 两种方式。这里我更推荐使用前者,因为后者对开发者有一定的要求,加入开发者某个耗时的业务订阅实现没有自行使用线程异步处理,则会影响其他处的订阅处理。

代码示例

1、添加 pom 依赖

        <!-- google EvengBus 在 guava 包中 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.2-jre</version>
        </dependency>
        <!-- lombok 非必须,其作用你懂得 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.28</version>
            <scope>provided</scope>
        </dependency>

2、创建一个Java接口用于自动注册

package com.example.demospringbean.eventbus;

/**
 * 用于自动注册事件订阅类的接口
 * 
 * @author shanhy
 * @date 2023-08-30 12:06
 */
public interface EventBusListener {
}

3、编写总配置类

package com.example.demospringbean.eventbus;

import com.google.common.eventbus.EventBus;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.List;

/**
 * EventBus 配置类
 *
 * @author shanhy
 * @date 2023-08-30 11:11
 */
@Configuration
public class EventBusConfiguration {

    /**
     * 实例化 EventBus 对象,并自动注册所有订阅类对象
     *
     * @param eventListenerList 所有实现了 EventBusListener 接口的实现类
     * @return
     */
    @Bean
    public EventBus eventBus(List<EventBusListener> eventListenerList){
        // 异步处理,按照自己需要,实现自己的 Executor 逻辑,例如为了防止线程长期占用需要增加超时机制等
//      EventBus eventBus = new AsyncEventBus(new Executor() {
//            public void execute(Runnable command) {
//                new Thread(command).start();
//            }
//        });
        EventBus eventBus = new EventBus();
        if(eventListenerList != null && !eventListenerList.isEmpty()) {
            eventListenerList.iterator().forEachRemaining(eventListener -> eventBus.register(eventListener));
        }
        return eventBus;
    }

}

4、编写订阅测试类

package com.example.demospringbean.eventbus;

import com.google.common.eventbus.Subscribe;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author shanhy
 * @date 2023-08-30 11:19
 */
@Component
public class EventSub1 implements EventBusListener {

    @Subscribe
    public void handlerEvent(String test) {
        System.out.println("11111>>>>>" + test);
    }

    @Subscribe
    public void handlerEvent2(String test) throws InterruptedException {
        TimeUnit.SECONDS.sleep(5);
        System.out.println("22222>>>>>" + test);
    }

}

package com.example.demospringbean.eventbus;

import lombok.Builder;
import lombok.Data;

/**
 * @author shanhy
 * @date 2023-08-30 13:19
 */
@Data
@Builder
public class User {

    private String name;
    private int age;

}

package com.example.demospringbean.eventbus;

import com.google.common.eventbus.Subscribe;
import org.springframework.stereotype.Component;

/**
 * @author shanhy
 * @date 2023-08-30 11:19
 */
@Component
public class EventSub2 implements EventBusListener {

    @Subscribe
    public void handlerEvent(String test){
        System.out.println("33333>>>>>" + test);
    }

    @Subscribe
    public void handlerEvent2(User user){
        System.out.println("44444>>>>>" + user.getName());
    }

}

5、编写消息事件发送测试

package com.example.demospringbean;

import com.example.demospringbean.eventbus.User;
import com.google.common.eventbus.EventBus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 接口示例
 *
 * @author shanhy
 * @date 2023-03-20 15:49
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @Autowired
    private EventBus eventBus;

    @GetMapping("/testEvent1")
    public String testEvent1(){
        eventBus.post("Hello");
        return "OK";
    }

    @GetMapping("/testEvent2")
    public String testEvent2(){
        eventBus.post(User.builder().name("Tome").age(22).build());
        return "OK";
    }
}

代码说明:

1、以上代码使用的 EventBus、未使用 AsyncEventBus,并加入了线程 sleep,是为了运行代码可以观察其串行处理效果(浏览器开2个Tab同时调用 /testEvent1 观察输出),让你能更明显的感受到这种处理会给程序带来多大的性能问题(推荐实际业务生产中使用 AsyncEventBus)。

2、@Subscribe 注解修饰的事件处理方法,其参数和发送事件时的消息体会自动按类型关联对应。只有相同类型的消息体才会被消费处理。例如示例中 /testEvent1 接口发送的 “Hello” 字符串,不会触发 handlerEvent2(User user) 方法的执行,同理执行示例中 /testEvent2 接口发送 User 对象时,只会触发 handlerEvent2(User user) 方法。


(END)文章来源地址https://www.toymoban.com/news/detail-694300.html

到了这里,关于SpringBoot - Google EventBus、AsyncEventBus的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • EventBus 开源库学习(三)

    上一节根据EventBus的使用流程把实现源码大体梳理了一遍,因为精力有限,所以看源码都是根据实现过程把基本流程看下,中间实现细节先忽略,否则越看越深不容易把握大体思路,这节把一些细节的部分再看看。 注解函数查找源码逻辑 在进行注册的时候,我们使用 subscri

    2024年02月14日
    浏览(33)
  • EventBus详解 (详解 + 原理)

    EventBus简介 EventBus是一个开源库,由GreenRobot开发而来,是用于Android开发的 “事件发布 — 订阅总线”, 用来进行模块间通信、解藕。 它可以使用很少的代码,来实现多组件之间的通信。 Android系统内置的事件通讯存在缺点: Android系统中的事件通信则是 handler ( 消息机制 ) 和

    2024年02月02日
    浏览(40)
  • eventBus使用遇到的坑

    **问题:**通过eventBus传递的参数,在子组件的methods中无法通过this.使用。 **思路:**考虑组件方法的执行顺序(vue生命周期执行顺序) **解决办法:**在传递参数的组件外 this.$nextTick 创建eventBus.js文件 在需要传递消息的兄弟组件引入该js文件 传递消息 bus.$emit(“test”,param1,pa

    2024年02月14日
    浏览(46)
  • Go语言EventBus

    EventBus是GoLang的小型轻量级事件总线,具有异步兼容性。 类似于观察者模式和发布订阅模式。 GitHub地址: https://github.com/asaskevich/EventBus 官方文档: https://pkg.go.dev/github.com/asaskevich/EventBus 1.1 安装 1.2 使用 进行封装: 订阅多个: Subscribe 可以放在 init 函数中: New() Subscribe() Su

    2024年02月11日
    浏览(34)
  • EventBus 开源库学习(二)

    EventBus在使用的时候基本分为以下几步: 1、注册订阅者 2、订阅者解注册,否者会导致内存泄漏 3、在订阅者中编写注解为Subscribe的事件处理函数 4、事件发送 我们先按使用的流程大体看下源码逻辑,源码版本3.3.1: 注册源码逻辑 EventBus 使用了双重校验锁的单例设计模式,保

    2024年02月14日
    浏览(38)
  • 微信小程序全局事件订阅eventBus

    微信小程序全局事件订阅 在Vue开发中,我们可能用过eventBus来解决全局范围内的事件订阅及触发逻辑,在微信小程序的开发中我们可能也也会遇到同样的需求,那么我们尝试下在小程序(原生小程序开发)中实现类似eventBus的事件订阅功能。 全局事件订阅 全局实例 在Vue中我

    2024年02月12日
    浏览(41)
  • flutter开发实战-事件总线EventBus实现

    flutter开发实战-事件总线EventBus实现 在开发中,经常会需要一个广播机制,用以跨Widget事件通知。 事件总线 实现了订阅者模式,订阅者模式包含发布者和订阅者两种角色,可以通过事件总线来触发事件和监听事件。 实现eventBus 在工程的pubspec.yaml引入库 1.使用event_bus库 创建一

    2024年02月15日
    浏览(43)
  • React V6实现类似与vue的eventBus

    功能背景 想要实现类似于vue的eventBus的功能,由一个组件通知其他一个或多个组件。应用场景:比如一个可视化大屏的界面,当筛选条件变化的时候,要同时通知到大屏中所有图表一起变化。(当然使用store也是可以的,eventbus就是相当于多了一个解决方案) 代码实现 eventB

    2024年02月11日
    浏览(48)
  • 【bug日记】报错“Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found”(通过google终于解决)

    Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found 看了网上十几篇的回答,大部分都是通过File-Invalidate Caches和增加version版本号解决的, 而我尝试了以上两种方法都无法解决!!! 最后通过google搜索相关解决方案,在评论中看到了一个解决方法 按照该方法后,成功解决

    2024年01月24日
    浏览(57)
  • 观察者模式(下):如何实现一个异步非阻塞的EventBus框架?

    上一节课中,我们学习了观察者模式的原理、实现、应用场景,重点介绍了不同应用场景下,几种不同的实现方式,包括:同步阻塞、异步非阻塞、进程内、进程间的实现方式。 同步阻塞是最经典的实现方式,主要是为了代码解耦;异步非阻塞除了能实现代码解耦之外,还能

    2024年02月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包