![](/img/trans.png)
[英]How to handle multiple listeners with same argument in google guava 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.
}
當您執行以下操作時:
您將獲得以下輸出:
啟動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.