Как указать подзависимость для AutoWired Beans - PullRequest
0 голосов
/ 04 июля 2019

У меня компонент 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 я могу сделать что-то вроде:

<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl"> 
    <constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>

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

1 Ответ

1 голос
/ 04 июля 2019

Используйте аннотацию @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 {
}

Объявление компонента в классе @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());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...