簡體   English   中英

使用Spring IoC在Guava EventBus中自動注冊bean

[英]Register beans automatically in Guava EventBus with Spring IoC

假設我的應用程序中有一個語言更改事件接口(它基於Vaadin):

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

我有很多bean實現了這個用@Component注釋的接口,因此它們可以在Spring IoC中使用。 我還有一個EventBus bean:

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

現在,在從IoC獲取任何bean的實例之后,我還必須得到一個languageSwitcher的實例,並在其中注冊newely創建的bean:

languageSwitcher.register(myNewBean);

為了接收這個事件。 有可能以某種方式告訴IoC我想在每個實現ILanguageChangeListener的新bean上調用languageSwitcher bean的register方法嗎?

好的,使用BeanPostProcessor,注冊接口的每個bean:

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

}

請注意,如果您有許多EventBus bean,則應使用ApplicationContext.getBean(String)來獲取所需的EventBus。

我引用javadoc

對於FactoryBean,將為FactoryBean實例和FactoryBean創建的對象(從Spring 2.0開始)調用此回調。 后處理器可以通過相應的Bean instanceof FactoryBean檢查來決定是應用於FactoryBean還是應用於創建的對象。

IMO,它更好(更少耦合),而不是實現標記接口,使用類級別注釋來標記應該注冊的bean。 這是修改后的bean后處理器代碼:

public class EventBusListenersRegistererBeanPostProcessor implements BeanPostProcessor{

    Logger log = LoggerFactory.getLogger(this.getClass());

    @Inject
    private EventBus bus;

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean.getClass().isAnnotationPresent(RegisterWithEventBus.class)){
            log.info("Event Bus is registering bean named \"{}\" of class {}.", beanName, bean.getClass().getCanonicalName());
            bus.register(bean);
        }

        return bean;
    }
}

和注釋:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Inherited // important when working with dynamically generated proxies i.e. CGLib
public @interface RegisterWithEventBus {}

請注意,注釋界面具有@Inherited元注釋。 這在使用CGLIB代理的Spring應用程序中是必需的,因為注釋不會在對象的實際(動態)類上,而是在父類上。

使用工廠bean作為事件總線,並在上下文中注入所有ILanguageChangeListener bean的列表。

public class EventBusFactoryBean implements FactoryBean<EventBus> {

    @Autowired
    private List<ILanguageChangeListener> languageChangeListeners;

    private EventBus instance;

    @PostConstruct
    public void init() {

        this.instance = new EventBus();

        for (ILanguageChangeListener listener : this.languageChangeListeners) {
            this.instance.register(listener);
        }
    }

    public EventBusFactoryBean() {

    }

    public EventBus getObject() throws Exception {
        return this.instance;
    }

    public Class<?> getObjectType() {
        return EventBus.class;
    }

    public boolean isSingleton() {
        return true;
    }

    public List<ILanguageChangeListener> getLanguageChangeListeners() {
        return languageChangeListeners;
    }

    public void setLanguageChangeListeners(
            List<ILanguageChangeListener> languageChangeListeners) {
        this.languageChangeListeners = languageChangeListeners;
    }

}

然后在Spring Bean Definition文件中定義bean或使用@Component注釋它

一種方法是使用接口InitializingBean並在bean中注入語言切換器。 像這樣的東西:

public class NotVeryUsefulLanguageListener implements ILanguageChangeListener,
        InitializingBean {

    @Autowired
    private EventBus languageSwitcher;

    public void afterPropertiesSet() throws Exception {

        this.languageSwitcher.register(this);
    }

    //... getters, setters, etc

}

如果NotVeryUsefulLanguageLisetener是單例,它只會發生一次......如果是原型然后每次從Spring獲得一個實例

如果您使用的是XML,那么您可以使用以下內容:

<bean id="languageListenerA" init-method="afterPropertiesSet" class="org.company.whatever.NotVeryUsefulLanguageListener">
        <!-- stuff -->
    </bean>

暫無
暫無

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

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