2012-04-16 26 views
0

我使用vaadin + spring IOC + google番石榴eventbus。 Resources建议将guava事件总线用作单例。但是当我这样做时,我有以下问题;谷歌guava singleton Eventbus多次触发

  • 假设我在3个不同的浏览器上同时运行应用程序,所以我有3个不同的应用程序实例。

  • 然后,例如,当我按下一个浏览器上的按钮并触发事件时,我注意到我的相关监听器方法和@subscribe批注被调用了3次!

这是我期望的正常行为,因为我使用eventbus作为单例吗?如果不是这里发生了什么? MainController是弹簧托管bean有一个自定义的Vaadin应用范围

class MainController{ 
    public MainController() throws DAOException, Exception { 
    EventBusFactory.getEventBusInstance().register(this); 
    } 

    @Subscribe 
    public void addFacetEvent(FacetAddedEvent event) throws DAOException { 
    getTreeTableView().addToList(event.getData()); 
    } 
} 

class EventBusFactory{ 
    public static EventBus getEventBusInstance() { 
     if(eventBus==null){ 
      eventBus=new EventBus(); 
     } 
     return eventBus; 
    } 
} 

P.S我也毫不犹豫地Vaadin我应该用番石榴eventbus或番石榴GWT事件总线?

感谢

+0

这听起来很奇怪,也是意想不到的。您的听众是否三次获得_registered_,或者事件是否发布三次? – 2012-04-17 01:26:03

+0

@Louis Wasserman我的订阅注释方法被调用3次,但事件只发布一​​次 – Spring 2012-04-17 07:23:47

+0

您注册听众的方式和位置? – Ray 2012-04-17 14:55:37

回答

3

简短的回答:这是在此配置(你有单EventBus管理3个Vaadin应用程序,因此3 MainController实例)正常和期望的行为。


通过定制Vaadin应用范围您的意思是this Vaadin addon范围是什么?

不管怎么说,这是简单的复制您的情况为原型作用域MainController豆和Vaadin应用程序是这样的:

public class SandpitApplication extends Application { 
    private static final long serialVersionUID = 1L; 
    private static final Logger log = Logger.getLogger(SandpitApplication.class); 

    // https://vaadin.com/wiki/-/wiki/Main/Spring%20Integration#section-Spring+Integration-SpringContextHelperClass 
    private SpringContextHelper ctx; 

    @Override 
    public void init() { 
    // vaadin stuff 
    setTheme("common"); 
    final Window mainWindow = new Window("Vaadin Sample Application"); 
    setMainWindow(mainWindow); 

    // get your bean from spring 
    log.info("start [email protected]" + Integer.toHexString(hashCode())); 
    ctx = new SpringContextHelper(this); 
    // create application-wide bean 
    final MainController mainController = ctx.getBean("mainController"); 

    mainWindow.addComponent(new Button("click to post", new Button.ClickListener() { 
     @Override public void buttonClick(final ClickEvent event) { 
     log.info("click on button"); 
     EventBusFactory.getEventBusInstance().post(
      new FacetAddedEventImpl("click-" 
       + new SimpleDateFormat("HH:mm:ss").format(new Date()))); 
     log.info(mainController); 
     } 
    })); 
    } 
} 

MainController类:

class MainController { 
    private static final Logger log = Logger.getLogger(MainController.class); 

    public MainController() { 
    log.info("creating [email protected]" + Integer.toHexString(hashCode())); 
    EventBusFactory.getEventBusInstance().register(this); 
    } 

    @Subscribe 
    public void addFacetEvent(final FacetAddedEvent event) { 
    final String signature = "[email protected]" + Integer.toHexString(hashCode()) + ": "; 
    log.info("addFacetEvent in " + signature + event); 
    // getTreeTableViewBuilder returns extended ArrayList with fancy add 
    getTreeTableViewBuilder().addFacetToList(signature + event.getData()); 
    } 

    // plus other stuff like toString etc. 
} 

当你做到以下几点:

  1. 在您的浏览器(应用程序#1)中启动vaadin应用程序。
  2. 单击App1#按钮。
  3. 启动另一个应用程序(应用程序#2)。
  4. 单击App2#按钮
  5. 回到应用程序1选项卡。
  6. 单击App1#按钮。

你会得到下面的输出:

开始SandpitApplication @ 75a5555a
创建MainController @ 2e98f864
点击按钮//#1
addFacetEvent在MC @ 2e98f864:FacetAddedEventImpl @ 6b527dc6 {data:click-13:42:45}
MainController @ 2e98f864 {treeTableViewBuilder:[MC @ 2e98f864:click-13:42:45]}
start SandpitApplication @ 3f9e529
创建MainController @ 2f8d604f
点击按钮//#2
addFacetEvent在MC @ 2e98f864:FacetAddedEventImpl @ 36c1fc67 {数据:点击-13:42:47}
addFacetEvent在MC @ 2f8d604f:FacetAddedEventImpl @ 36c1fc67 {数据:点击-13:42:47}
MainController @ 2f8d604f {treeTableViewBuilder:[MC @ 2f8d604f:点击-13:42:47]}
点击按钮//#1
addFacetEvent在MC @ 2e98f864:FacetAddedEventImpl @ 42d32028 {data:click-13:42:49}
MC @ 2f8d604f中的addFacetEvent:FacetAddedEventImpl @ 42d32028 {data:click-13:42:49}
M ainController @ 2e98f864 {treeTableViewBuilder:[MC @ 2e98f864:点击-13:42:45,MC @ 2e98f864:点击-13:42:47,MC @ 2e98f864:点击-13:42:49]}

您现在应该看到单身人员EventBus正在管理两个应用程序范围的MainController bean,并且每个都是接收事件(因为它已通过全局EventBus解决)。

试图猜测你想实现的,我会说,你需要创建应用程序范围内事件总线豆什么:

<bean id="eventBus" class="com.google.common.eventbus.EventBus" 
    scope="vaadinApplication" /> 

关于PS:我们在Vaadin项目中使用标准的番石榴广泛地说,不需要GWT版本。

+0

感谢您的详细解答,我会尝试您的建议 – Spring 2012-04-20 08:15:23