Springboot Guava Eventbus简单使用

简单介绍

EventBus是 Google Guava 提供的一个事件总线库,用于简化组件之间的通信。它基于发布-订阅模式,允许组件在不直接依赖彼此的情况下进行通信。在一个应用程序中,当某个组件触发了一个事件,所有订阅了该事件的组件都会收到通知并执行相应的操作。

简单来说,EventBus 可以帮助你解耦代码,使得组件之间更加灵活和独立。

简单使用

  1. 事件(Event)

    事件是系统中某一特定状态的表示,可以是用户操作、系统状态改变等。通常是一个普通的POJO对象,用于封装事件相关的数据。

    1
    2
    3
    4
    5
    @Data
    public class MyEvent {
    private String message;
    ..........
    }
  2. 事件发布者(Event Publisher)

    负责发布事件的组件,通常是某个服务、控制器或其他业务逻辑组件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Slf4j
    @Component
    public class MyEventBus extends EventBus {

    @Override
    public void register(Object object) {
    log.info("{} 订阅成功 ", object.getClass().getSimpleName());
    super.register(object);
    }

    @Override
    public void unregister(Object object) {
    log.info("{} 移除订阅成功 ", object.getClass().getSimpleName());
    super.unregister(object);
    }

    @Override
    public void post(Object event) {
    log.info("notify : {}", JSON.toJSONString(event));
    super.post(event);
    }
    }
  3. 事件订阅者(Event Subscriber)

    负责订阅并处理特定类型事件的组件,通常是一个或多个。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class MyEventBusSubscribe{

    @Autowired
    private MyEventBus eventBus;

    @PostConstruct
    public void register() {
    eventBus.register(this);
    }

    @Subscribe
    public void update(MyEvent t){
    //执行业务
    }
    }
  4. 使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    //依赖注入
    @Autowired
    private MyEventBus myEventBus;

    //定义消息
    MyEvent myevent=new MyEvent();
    myevent.setMessage("message");
    //发送消息
    myEventBus.post(myevent);

同步消费-EventBus

EventBus 是按照先到先服务(FIFO)的顺序依次处理事件的。也就是说,当一个事件被发布后,EventBus 会依次通知所有订阅者并让它们处理该事件,只有当当前事件的所有订阅者处理完成后,EventBus 才会发布下一个事件。

验证代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Random;

// 定义一个事件类
@Data
@AllArgsConstructor
class MessageEvent {
private String message;
}

// 定义一个订阅者
class MessageSubscriber {
@Subscribe
public void receiveMessage(MessageEvent event) throws InterruptedException {
System.out.println("Received message: " + event.getMessage());
Thread.sleep((new Random().nextInt(5) + 1) * 1000);
}
}

public class demo {
public static void main(String[] args) {
// 创建一个事件总线
EventBus eventBus = new EventBus();
// 注册订阅者
MessageSubscriber subscriber = new MessageSubscriber();
eventBus.register(subscriber);
// 发布事件
eventBus.post(new MessageEvent("Hello, EventBus1!"));
eventBus.post(new MessageEvent("Hello, EventBus2!"));
eventBus.post(new MessageEvent("Hello, EventBus3!"));
eventBus.post(new MessageEvent("Hello, EventBus4!"));
eventBus.post(new MessageEvent("Hello, EventBus5!"));
}
}

image-20240412183032548

(图片展示为即使消费速度快慢不同仍依次消费)

异步消费-AsyncEventBus

对于AsyncEventBus.post方法会立即将事件加入到事件队列中,但它并不会等待事件的消费者(订阅者)处理完一条消息再继续发布下一条消息。相反,它会在将事件放入队列后立即返回,允许代码继续执行。

异步事件处理的机制会确保订阅者在后台线程中处理事件,因此即使在一条事件还未被完全处理完成时,AsyncEventBus 也可以接受和处理其他事件。

这意味着,在使用 AsyncEventBus 时,即使在短时间内多次调用 post 方法来发布多个事件,它们也会被立即加入到事件队列中,并在后台线程中异步处理。

验证代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.Subscribe;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Random;
import java.util.concurrent.Executors;

// 定义一个事件类
@Data
@AllArgsConstructor
class MessageEvent {
private String message;
}

// 定义一个订阅者
class MessageSubscriber {
@Subscribe
public void receiveMessage(MessageEvent event) throws InterruptedException {
System.out.println("Received message: " + event.getMessage());
Thread.sleep((new Random().nextInt(5) + 1) * 1000);
}
}

public class demo {
public static void main(String[] args) {
// 创建一个异步事件总线
AsyncEventBus eventBus = new AsyncEventBus(Executors.newCachedThreadPool());
// 注册订阅者
MessageSubscriber subscriber = new MessageSubscriber();
eventBus.register(subscriber);
// 发布事件
eventBus.post(new MessageEvent("Hello, EventBus1!"));
eventBus.post(new MessageEvent("Hello, EventBus2!"));
eventBus.post(new MessageEvent("Hello, EventBus3!"));
eventBus.post(new MessageEvent("Hello, EventBus4!"));
eventBus.post(new MessageEvent("Hello, EventBus5!"));
}
}

image-20240412185436477

(图片展示为消费速度快慢不同导致执行结果次序不同)

Springboot Guava Eventbus简单使用
https://cason.work/2024/04/12/Springboot-Guava-Eventbus简单使用/
作者
Cason Mo
发布于
2024年4月12日
许可协议