Search code examples
javaspringguavavaadinevent-bus

Register beans automatically in Guava EventBus with Spring IoC


Let's say I have an interface for language change event in my application (it's based on Vaadin):

public interface ILanguageChangeListener{
    @Subscribe onLanguageChange(LanguageChangeEvent event);
}

And I have many beans that implements this interface annotated with @Component, thus they are available in Spring IoC. I have also an EventBus bean:

<bean id="languageSwitcher" class="com.google.common.eventbus" scope="session" />

Now, after getting an instance of any bean from IoC I have to get also an instance of the languageSwitcher and register the newely created bean in it with:

languageSwitcher.register(myNewBean);

in order to receive this events. Is it possible to somehow tell the IoC that I want to call the register method of the languageSwitcher bean on every new bean that implements the ILanguageChangeListener?


Solution

  • OK, using a BeanPostProcessor, register every bean of your interface:

    public class EventBusRegisterBeanPostProcessor implements BeanPostProcessor,
            ApplicationContextAware {
    
        private ApplicationContext context;
    
        @Autowired
        private EventBus eventBus; // The only event bus i assume...
    
        public Object postProcessBeforeInitialization(Object bean, String beanName)
                throws BeansException {
    
            return bean;
        }
    
        public Object postProcessAfterInitialization(Object bean, String beanName)
                throws BeansException {
    
            if (bean instanceof ILanguageChangeListener) {
                registerToEventBus(bean);
            }
    
            return bean;
        }
    
        private void registerToEventBus(Object bean) {
            this.eventBus.register(bean);
        }
    
        public void setApplicationContext(ApplicationContext applicationContext)
                throws BeansException {
            this.context = applicationContext;
        }
    
    }
    

    Note that if you have many EventBus beans, you should use the ApplicationContext.getBean(String) to get the EventBus you need.

    I quote from the javadoc:

    In case of a FactoryBean, this callback will be invoked for both the FactoryBean instance and the objects created by the FactoryBean (as of Spring 2.0). The post-processor can decide whether to apply to either the FactoryBean or created objects or both through corresponding bean instanceof FactoryBean checks.