当前位置: 首页 > 知识库问答 >
问题:

在Spring,确保在分派事件之前实例化Guava Event Bus侦听器bean

邵昆琦
2023-03-14

假设我有以下情况:

配置

设置番石榴事件总线豆。

@Configuration
public class AppConfig {

    @Bean
    public EventBus eventBus() {
        return new EventBus(); // guava event bus
    }
}

事件侦听器

监听并处理事件总线上的部分/全部事件。可能有几个与此类似的不同类,用于订阅应用程序中的事件。

@Component
public class EventListener {

    @Autowired
    public EventListener(EventBus eventBus) {
        eventBus.register(this); // register this instance with the event bus so it receives any events
    }

    @Subscribe
    public void onTestEvent(TestEvent e) {
        System.out.println("Caught event");
    }
}

事件调度员

将事件放到事件总线上的东西。

@Component
public class EventDispatcher {
    @Autowired
    public EventDispatcher(EventBus eventBus) {
        eventBus.post(new TestEvent());
    }
}

主应用入口点

@ComponentScan
@EnableAutoConfiguration
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

如何确保在发布事件的类之前实例化所有正在侦听事件的类?即目前,事件调度程序类可以在实例化侦听器之前实例化并发布事件,这意味着侦听器会错过事件。

我在想也许可以创建另一个注释,比如@EventListener,然后让Spring以某种方式优先考虑带有该注释的所有类,但不确定如何实现它,或者这是否真的是一个好主意。

谢谢

共有1个答案

夹谷俊远
2023-03-14

我决定扩展Guava EventBus类,创建< code>BufferedEventBus。

这只是缓冲发布到它的任何事件对象,直到应用程序上下文完成加载。发生这种情况时,它会发布任何缓冲的事件。任何未来的事件都会立即发布而不是缓冲。

缓冲区

package tjenkinson.events;

import java.util.ArrayList;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service;

import com.google.common.eventbus.EventBus;

/**
 * A guava event bus that holds back any events that are posted to it until the application
 * context has finished loading meaning all eager-loaded beans will have been constructed.
 * 
 * This means any eager-loaded beans that want to listen to events on this event bus will be able
 * to and not miss any events that were posted from other beans before they had a chance to listen.
 */

@Service
public class BufferedEventBus extends EventBus implements ApplicationListener<ContextRefreshedEvent> {

    private boolean applicationContextLoaded = false;
    private final ArrayList<Object> bufferedEvents = new ArrayList<>();

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        synchronized(bufferedEvents) {
            if (applicationContextLoaded) {
                // context already loaded. maybe it's been refreshed.
                return;
            }

            postBufferedEvents();
            applicationContextLoaded = true;
        }
    }

    @Override
    public void post(Object event) {
        synchronized(bufferedEvents) {
            if (applicationContextLoaded) {
                super.post(event);
            }
            else {
                bufferedEvents.add(event);
            }
        }
    }

    private void postBufferedEvents() {
        synchronized(bufferedEvents) {
            for (Object event : bufferedEvents) {
                super.post(event);
            }
            bufferedEvents.clear();
        }
    }

}

我现在只是在整个应用程序中使用它,而不是标准的<code>EventBus</code>。

 类似资料:
  • 将事件侦听器添加到可以使用事件委派的元素。 使用 EventTarget.addEventListener() 将一个事件监听器添加到一个元素。 如果提供了 选项对象(opts) 的 target 属性,确保事件目标匹配指定的目标元素,然后通过提供正确的 this 上下文来调用回调。 返回一个对自定义委派函数的引用,以便与 off 一起使用。 忽略 opts ,则默认为非委派行为,并且事件冒泡。

  • 在Spring应用程序启动时,我想在Redis中查找一个值,并根据该值关闭或保留消息侦听器。 完全不初始化这些bean也是可以的,但是我也找不到方法。 目前,我正在尝试使用Spring的关闭容器: 容器 消息侦听器: 问题是,如果我用已经在队列中的消息启动应用程序,消息侦听器将在执行之前拾取消息。 有办法实现我的目标吗?即使采用不同的方法

  • 我正在Wildfly 9.0.1的KeyClope中配置一个事件侦听器。我创造了一个。jar有两个类,实现了一个提供者,如KeyClope在他的github示例中解释的那样。 在本例中,keydape人员解释说,有必要注册提供者编辑“standalone/configuration/standalone.xml”并将模块添加到providers元素中。我在标签“subsystem”中对这个定义进行

  • 我使用JMS从IBM MQ message Broker发送接收消息。我目前正在处理侦听器服务,抛出未处理的异常和消息发送回队列而没有确认。我希望服务重试一个可配置的次数,并抛出表示监听器服务不可用的完全异常消息。 我的监听器和容器工厂如下所示。

  • 我有一个控制器类,它需要为列表中的每个项目执行各种异步操作: 对于每个A 播放音频并等待完成 等t秒 对于A的每个子部分B: 播放音频并等待 等待t2秒 当我的方法被激发。我试着回复听众: 但最后我还是无法摆脱内部循环,这让我觉得整个想法都行不通。我已经查看了未来的界面,但这似乎也不是我想要的。 我知道我可以用一堆变量来解决这个问题,以跟踪我在状态流中的位置,但是带有一些框架的循环会更干净。谢谢:

  • 你好,有一种方式鼠标,甚至可以举行鼠标和释放,因为我不能找到它在谷歌。 例如这张图片… 当为时,单击该按钮,他会看到······然后,在他释放鼠标单击后,将再次返回