我有一个这样定义的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到应使用的bean?我知道我可以使用@Qualifier
批注,但这会将索引更新程序硬编码为实现之一,同时我希望用户能够指定要使用的索引更新程序。在XML中,我可以做类似的事情:
<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl">
<constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>
如何使用Spring的Java批注做同样的事情?
答案 0 :(得分:1)
使用@Qualifier
批注指定要使用的依赖项:
public SearchIndexImpl(@Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
请注意,自Spring 4开始,不需要@Autowired
来自动装配bean的arg构造函数。
回答您的评论。
要让将使用Bean的类定义依赖关系,可以使用它来定义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类中声明Bean:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
SearchIndexImpl
bean现在将解决依赖关系,这要归功于IndexUpdater getIndexUpdater()
。
在这里,我们将@Component
用于一个bean,并将@Bean
用于其依赖性。
但是我们也可以通过仅使用@Bean
并通过删除3个类上的@Component
来实例化Bean的完全控制:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
@Bean
public SearchIndexImpl getSearchIndexFoo(){
return new SearchIndexImpl(getIndexUpdater());
}