簡體   English   中英

Google Guava Singleton Eventbus多次觸發

[英]Google guava singleton Eventbus fires multiple times

我使用vaadin +春季IOC +谷歌番石榴eventbus。 參考資料建議使用guava eventbus作為單例。 但是當我這樣做時,我遇到了以下問題;

  • 假設我同時在3個不同的瀏覽器上運行該應用程序,因此我有3個不同的應用程序實例。

  • 然后,例如,當我按下一個瀏覽器上的按鈕並觸發事件時,我注意到帶有@subscribe批注的相關偵聽器方法被調用了3次!

這是我期望的正常行為,因為我將事件總線用作單例嗎? 如果不是,這是怎么回事? MainController是具有自定義Vaadin應用范圍的Spring托管bean

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;
    }
}

ps我也在Vaadin猶豫,我應該使用guava eventbus還是guava gwt event bus?

謝謝

簡短的答案:在這種配置下,這是正常的和預期的行為(您具有三個Vaadin應用程序,因此具有三個由單個EventBus管理的MainController實例)。


通過自定義Vaadin應用程序范圍 ,您是指這個Vaadin插件的范圍嗎?

無論如何,使用如下所示的原型作用域的MainController bean和Vaadin App重現您的情況很簡單:

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 SandpitApplication@" + 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 MainController@" + Integer.toHexString(hashCode()));
    EventBusFactory.getEventBusInstance().register(this);
  }

  @Subscribe
  public void addFacetEvent(final FacetAddedEvent event) {
    final String signature = "MC@" + 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. 在瀏覽器(App#1)中啟動vaadin應用。
  2. 單擊“ App1#”按鈕。
  3. 啟動另一個應用程序(App#2)。
  4. 單擊App2#按鈕
  5. 使用App#1返回標簽。
  6. 單擊“ App1#”按鈕。

您將獲得以下輸出:

啟動SandpitApplication @ 75a5555a
創建MainController @ 2e98f864
單擊按鈕//#1
MC @ 2e98f864中的addFacetEvent:FacetAddedEventImpl @ 6b527dc6 {data:click-13:42:45}
MainController @ 2e98f864 {treeTableViewBuilder:[MC @ 2e98f864:click-13:42:45]}
啟動SandpitApplication @ 3f9e529
創建MainController @ 2f8d604f
單擊按鈕//#2
MC @ 2e98f864中的addFacetEvent:FacetAddedEventImpl @ 36c1fc67 {data:click-13:42:47}
MC @ 2f8d604f中的addFacetEvent:FacetAddedEventImpl @ 36c1fc67 {data:click-13:42:47}
MainController @ 2f8d604f {treeTableViewBuilder:[MC @ 2f8d604f:click-13:42:47]}
單擊按鈕//#1
MC @ 2e98f864中的addFacetEvent:FacetAddedEventImpl @ 42d32028 {data:click-13:42:49}
MC @ 2f8d604f中的addFacetEvent:FacetAddedEventImpl @ 42d32028 {data:click-13:42:49}
MainController @ 2e98f864 {treeTableViewBuilder:[MC @ 2e98f864:click-13:42:45,MC @ 2e98f864:click-13:42:47,MC @ 2e98f864:click-13:42:49]}

現在,您應該看到Singleton EventBus正在管理兩個應用程序范圍的MainController Bean,並且每個都在接收事件(因為它由全局EventBus解決)。

為了猜測您要實現的目標,我想您需要創建應用程序范圍的事件總線bean:

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

關於PS:我們在Vaadin項目中廣泛使用標准番石榴,不需要GWT版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM