0

私はvaadin+spring IOC + googleguavaeventbusを使用しています。リソースでは、グアバイベントバスをシングルトンとして使用することを推奨しています。しかし、それを行うと、次の問題が発生します。

  • たとえば、3つの異なるブラウザーで同時にアプリケーションを実行しているため、アプリケーションの3つの異なるインスタンスがあります。

  • たとえば、あるブラウザのボタンを押してイベントを発生させると、@subscribeアノテーションを持つ関連するリスナーメソッドが3回呼び出されることに気付きます。

これは、イベントバスをシングルトンとして使用しているため、私が期待する通常の動作ですか?そうでなければ、ここで何が起こっているのでしょうか?MainControllerは、カスタムVaadinアプリケーションスコープを備えたスプリングマネージド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で躊躇しますが、グアバイベントバスまたはグアバgwtイベントバスを使用する必要がありますか?

ありがとう

4

1 に答える 1

3

簡単な答え:この構成では、これは正常で予想される動作です(3つのVaadinアプリケーションがあるため、3つのMainControllerインスタンスが単一で管理されますEventBus)。


カスタムVaadinアプリケーションスコープとは、このVaadinアドオンのスコープを意味しますか?

とにかく、プロトタイプスコープのMainControllerBeanとVaadinAppを使用すると、次のように状況を簡単に再現できます。

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. ブラウザでvaadinアプリを起動します(App#1)。
  2. App1#ボタンをクリックします。
  3. 別のアプリを起動します(アプリ#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]}
Start SandpitApplication @ 3f9e529 create
MainController @ 2f8d604f
click on button //#2
addFacetEvent in MC @ 2e98f864:FacetAddedEventImpl @ 36c1fc67 {data:click-13:42:47}
addFacetEvent in MC @ 2f8d604f:FacetAddedEventImpl @ 36c1fc67 {データ:クリック-13:42:47}
MainController @ 2f8d604f {treeTableViewBuilder:[MC @ 2f8d604f:クリック-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 :クリック-13:42:45、MC @ 2e98f864:クリック-13:42:47、MC @ 2e98f864:クリック-13:42:49]}

これで、シングルトンEventBusが2つのアプリケーション全体のMainControllerBeanを管理し、それぞれがイベントを受信して​​いることがわかります(グローバルによって解決されるためEventBus)。

何を達成したいのかを推測しようとすると、アプリケーション全体のイベントバスBeanを作成する必要があると思います。

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

PSについて:Vaadinプロジェクトでは標準のGuavaを幅広く使用しており、GWTバージョンは必要ありません。

于 2012-04-19T12:18:40.680 に答える