春季范围事件可能吗?

时间:2018-07-18 07:33:56

标签: java spring vaadin

Spring事件机制支持发布应用程序事件并通过@EventListener批注在Spring组件中侦听这些事件。但是,在documentation中找不到关于在特定范围内发送事件的任何信息。我对Vaadin的具体需求是:

  • 在用户交互的情况下,发送事件(例如,已登录事件)
  • 此事件仅应由同一@UIScope中的bean占用,即,不应影响其他用户UI

有可能吗?注意:这并不是Vaadin特有的。我还可以问一下Spring Web MVC请求范围如何实现。

2 个答案:

答案 0 :(得分:1)

TL; DR:我认为它已经可以按照您的要求进行工作

长版:

文档尚不清楚,但是尝试了一个简单的测试:

发布事件的控制器:

@Controller
public class FooController {
    @Autowired
    private ApplicationEventPublisher publisher;

    @GetMapping("/fireEvent")
    public void fireEvent() {
        publisher.publishEvent(new FooEvent(this));
    }
}

还有一个侦听的作用域Bean:

@Scope(value = WebApplicationContext.SCOPE_REQUEST)
@Component
public class FooListener {
    @EventListener(FooEvent.class)
    public void listen() {
         System.out.println("I'm listening. PS : I am "+this.toString());
    }
}

并且在运行两个并发请求时,只有作用域相同的httprequest的侦听器才能获取事件。


我的解释(由于没有真正深入地研究过,因此请带一点盐):

在我看来,ApplicationEventMulticaster的{​​{1}}使用BeanFactory来获取先前已注册为侦听器(按其名称)的bean。显然,工厂将在当前范围内返回一个bean。

答案 1 :(得分:0)

请查看这是否是您想要的:

主要应用程序:

   package com.fg7.evision.EventList;

    import org.springframework.context.annotation.AnnotationConfigApplicationContext;
    import org.springframework.context.annotation.ComponentScan;

    @ComponentScan(basePackages = "com.fg7.evision.EventList")
    public class EventApplication {


        public static void main(String[] args) {
           MyScopedEvent event = new MyScopedEvent("hello world");
           AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(EventApplication.class);
            ctx.publishEvent(event);
        }

    }

事件:

 package com.fg7.evision.EventList;

    public class MyScopedEvent  {

        private String message;

        public MyScopedEvent( String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }

事件侦听器仅作用于Singleton作用域。

package com.fg7.evision.EventList;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

@Component(value = "listener")
public class ScopedEventListener implements BeanNameAware {

    @Autowired
    ConfigurableApplicationContext context;

    String beanName;

    @Override
    public void setBeanName(String name) {
        this.beanName = name;
    }

    @EventListener(condition = "@listener.getScope() == 'singleton'")
    public void handleEvent(MyScopedEvent myScopedEvent) {
        System.out.println(myScopedEvent.getMessage());

    }

    public String getScope(){
        return this.context.getBeanFactory().getBeanDefinition(this.beanName).getScope();
    }


}