от
У меня есть компонент Spring, определенный следующим образом:
@Component
public class SearchIndexImpl implements SearchIndex {
    IndexUpdater indexUpdater;

    @Autowired
    public SearchIndexImpl(final IndexUpdater indexUpdater) {
        Preconditions.checkNotNull(indexUpdater);
        this.indexUpdater = indexUpdater;
    }
}
наряду с двумя реализациями интерфейса
IndexUpdater
, например:
@Component
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {

}

@Component
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
Если я попытаюсь автоматически подключить
SearchIndexImpl
следующим образом:
@Autowired
private SearchIndex searchIndex;
Я получаю следующее исключение:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'IndexUpdater' available: expected single matching bean but found 2: indexDirectUpdater,indexQueueUpdater
что ожидается, так как Spring не может сказать, какую реализацию
IndexUpdater
автоматически подключить для параметра
indexUpdater
в конструкторе
SearchIndexImpl
. Как мне привести Spring к бину, который он должен использовать? Я понимаю, что могу использовать аннотацию
@Qualifier
, но это жестко закодирует средство обновления индекса в одной из реализаций, в то время как я хочу, чтобы пользователь мог указать, какой модуль обновления индекса использовать. В XML я могу сделать что-то вроде:
 
    <constructor

Как мне сделать то же самое, используя аннотации Spring в Java?
    

        

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.
Анти-спам проверка:
Чтобы избежать проверки в будущем, пожалуйста войдите или зарегистрируйтесь.

1 Ответ

0 голосов
от
Используйте аннотацию
@Qualifier
, чтобы указать используемую зависимость:
public SearchIndexImpl(@Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
    Preconditions.checkNotNull(indexUpdater);
    this.indexUpdater = indexUpdater;
}
Обратите внимание, что
@Autowired
не требуется для автоматического связывания конструктора arg бина начиная с Spring 4. Ответить на ваш комментарий. Чтобы позволить классу, который будет использовать бин для определения используемой зависимости, вы можете разрешить ему определять экземпляр
IndexUpdater
для внедрения в контейнер, такой как:
// @Component not required any longer
public class IndexDirectUpdater implements IndexUpdater, DisposableBean, InitializingBean {

}

// @Component not required any longer
public class IndexQueueUpdater implements IndexUpdater, DisposableBean, InitializingBean {
}
Объявите bean-компонент в классе @Configuration:
@Configuration
public class MyConfiguration{

@Bean
public IndexUpdater getIndexUpdater(){
     return new IndexDirectUpdater();
}
Компонент
SearchIndexImpl
теперь разрешает зависимость благодаря
IndexUpdater getIndexUpdater()
. Здесь мы используем
@Component
для одного компонента и
@Bean
для его зависимости. Но мы также могли бы разрешить создание полного контроля над bean-компонентами, используя только
@Bean
и удалив
@Component
из 3 классов:
@Configuration
public class MyConfiguration{

@Bean
public IndexUpdater getIndexUpdater(){
     return new IndexDirectUpdater();
}

@Bean 
public SearchIndexImpl getSearchIndexFoo(){
     return new SearchIndexImpl(getIndexUpdater());
}
    
...