简体   繁体   English

Guava EventBus:向多个订阅者调度事件

[英]Guava EventBus: Dispatching event to multiple subscribers

Since the Guava's EventBus documentation is rather short I ask it here: 由于Guava的EventBus文档很短,我在这里问:

Is there a way to dispatch events to multiple subscribers or are events always consumed by the first suitable subscriber? 有没有办法将事件分派给多个订户,或者是第一个合适的订户总是消费的事件?

If the latter is the case, would it better to extend the EventBus class in order to add such a feature or to implement the whole event bus logic in the own application? 如果是后者,那么扩展EventBus类以便添加这样的功能或在自己的应用程序中实现整个事件总线逻辑会更好吗?

Events are routed to all registered subscribers as long as they match the event type. 只要事件与事件类型匹配,事件就会路由到所有已注册的订户。

It's in the Javadoc of EventBus : 它位于EventBusJavadoc中:

Posting Events 发布活动

To post an event, simply provide the event object to the post(Object) method. 要发布事件,只需将事件对象提供给post(Object)方法即可。 The EventBus instance will determine the type of event and route it to all registered listeners. EventBus实例将确定事件的类型并将其路由到所有已注册的侦听器。

Events are routed based on their type — an event will be delivered to any subscriber for any type to which the event is assignable. 事件根据其类型进行路由 - 事件将被传递给任何订阅者,以用于可分配事件的任何类型。 This includes implemented interfaces, all superclasses, and all interfaces implemented by superclasses. 这包括已实现的接口,所有超类以及超类实现的所有接口。

If the latter is the case, would it better to extend the EventBus class in order to add such a feature or to implement the whole event bus logic in the own application? 如果是后者,那么扩展EventBus类以便添加这样的功能或在自己的应用程序中实现整个事件总线逻辑会更好吗?

I guess, all you need is to add a handled attribute to the event and add a testAndSet to all your handlers. 我想,您只需要为事件添加一个handled属性,并为所有处理程序添加一个testAndSet Doing it manually is surely error-prone, if you have many of them. 如果您有很多这样的话,那么手动操作肯定容易出错。

You could create a wrapper for your event, which wouldn't let you access it without calling it. 您可以为事件创建一个包装器,这样就不会在不调用它的情况下访问它。 Something like 就像是

@RequiredArgsConstructor
class WrappedEvent<E extends MyEvent> {
    private final E event;
    private boolean handled;

    Optional<E> getAndMarkHandledUnlessHandled() {
        if (handled) {
            return Optional.empty();
        } else {
            handled = true;
            return Optional.of(event);
        }
    }
}

or do it in more functional way like callAndMarkHandledUnlessHandled(Consumer<E> consumer) . 或者以更加实用的方式执行,如callAndMarkHandledUnlessHandled(Consumer<E> consumer) For asynchronous dispatch, you'd use an AtomicBoolean . 对于异步调度,您将使用AtomicBoolean

However, because of erasure, this won't work with WrappedEvent<A> and WrappedEvent<B> as the EventBus has no generic information available. 但是,由于擦除,这不适用于WrappedEvent<A>WrappedEvent<B>因为EventBus没有可用的通用信息。 You could subclass the wrapper like WrappedA extends WrappedEvent<A> {} and work with it. 您可以像WrappedA extends WrappedEvent<A> {}一样WrappedA extends WrappedEvent<A> {}包装器并使用它。 It's damn ugly. 真该死。

Meaningfully extending the EventBus is hardly possible, if you don't want to sneak into its package. 如果您不想潜入其包装,那么有意义地扩展EventBus几乎是不可能的。 The easiest way would probably be forking the whole package and the adding a break after this line . 最简单的方法可能是分配整个包并在此行之后添加一个中断。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM