请求范围的ApplicationEventListener无法接收事件

Mar*_*nik 5 java spring spring-mvc

我需要为每个请求注册一个单独的应用程序事件监听器.侦听器的目的是捕获来自其他REST请求的事件,同时阻止侦听器的请求等待所有必需的事件进入.

我有这样的代码:

@Component
// @Scope(WebApplicationContext.SCOPE_REQUEST)
public static class WhistleEventListener implements ApplicationListener<WhistleEvent> {
  volatile Consumer<WhistleEvent> handler;
  @Override
  public void onApplicationEvent(WhistleEvent we) {
    final Consumer<WhistleEvent> h = handler;
    if (h != null) h.accept(we);
  }
}
@Autowired WhistleEventListener whistleEventListener;
Run Code Online (Sandbox Code Playgroud)

此代码接收事件,但是一旦取消注释@Scope注释,它就会停止接收事件.

是否支持请求范围的应用程序事件侦听器,它们应该可以工作吗?如果是这样,我可以做些什么让我的听众工作吗?

mer*_*ike 2

我怀疑您对应用程序事件分派机制存在误解:事件是根据 bean定义而不是 bean实例分派的,并且每个 bean 定义在事件发布时并在上下文中解析为一个实例。这意味着您的事件将仅分派到属于发布事件的请求的请求范围 bean ,但您希望通知所有当前请求的侦听器。

更一般地说,范围的目的是隔离范围实例,其中包含单独的 bean 实例。如果您不希望隔离,则应使用没有单独实例的作用域,例如应用程序作用域。

也就是说,要将事件分派到其他作用域实例,您必须自己进行分派,例如:

@Component
public class WhistleEventMediator implements ApplicationListener<WhistleEvent> {
    // TODO: make thread safe
    final Set<Consumer<WhistleEvent>> consumers; 

    void subscribe(Consumer<WhistleEvent> c) { ... }

    void unsubscribe(Consumer<WhistleEvent> c) { ... }

    @Override public void onApplicationEvent(WhistleEvent we) {
        // delegate to subscribed consumers
    }
}

@Component 
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class WhateverBean implements Consumer<WhistleEvent> {
    @Inject
    WhistleEventMediator mediator;

    @PostConstruct
    void init() {
        mediator.subscribe(this);
    }

    @PreDestroy
    void destroy() {
        mediator.unsubscribe(this);
    }

    // handle whistle event
}
Run Code Online (Sandbox Code Playgroud)