如何为 AutoWired Bean 指定子依赖
How to specify sub-dependency for AutoWired Beans
我有一个这样定义的 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 无法判断要为 SearchIndexImpl
的构造函数中的 indexUpdater
参数自动连接哪个 IndexUpdater
实现。如何将 Spring 引导至它应该使用的 bean?我知道我可以使用 @Qualifier
注释,但这会将索引更新程序硬编码为实现之一,同时我希望用户能够指定要使用的索引更新程序。在 XML 中,我可以做类似的事情:
<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl">
<constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>
如何使用 Spring 的 Java 注释来做同样的事情?
使用 @Qualifier
注释指定要使用的依赖项:
public SearchIndexImpl(@Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
请注意,自 Spring 4 以来,不需要 @Autowired
来自动装配 bean 的 arg 构造函数。
回复您的评论。
要让 class 将使用 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 class 中声明 bean:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
由于 IndexUpdater getIndexUpdater()
,SearchIndexImpl
bean 现在将解决依赖关系。
这里我们对一个 bean 使用 @Component
,对它的依赖使用 @Bean
。
但是我们也可以通过仅使用 @Bean
并删除 3 classes 上的 @Component
来允许对要实例化的 bean 进行完全控制:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
@Bean
public SearchIndexImpl getSearchIndexFoo(){
return new SearchIndexImpl(getIndexUpdater());
}
我有一个这样定义的 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 无法判断要为 SearchIndexImpl
的构造函数中的 indexUpdater
参数自动连接哪个 IndexUpdater
实现。如何将 Spring 引导至它应该使用的 bean?我知道我可以使用 @Qualifier
注释,但这会将索引更新程序硬编码为实现之一,同时我希望用户能够指定要使用的索引更新程序。在 XML 中,我可以做类似的事情:
<bean id="searchIndexWithDirectUpdater" class="SearchIndexImpl">
<constructor-arg index="0" ref="indexDirectUpdater"/>
</bean>
如何使用 Spring 的 Java 注释来做同样的事情?
使用 @Qualifier
注释指定要使用的依赖项:
public SearchIndexImpl(@Qualifier("indexDirectUpdater") IndexUpdater indexUpdater) {
Preconditions.checkNotNull(indexUpdater);
this.indexUpdater = indexUpdater;
}
请注意,自 Spring 4 以来,不需要 @Autowired
来自动装配 bean 的 arg 构造函数。
回复您的评论。
要让 class 将使用 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 class 中声明 bean:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
由于 IndexUpdater getIndexUpdater()
,SearchIndexImpl
bean 现在将解决依赖关系。
这里我们对一个 bean 使用 @Component
,对它的依赖使用 @Bean
。
但是我们也可以通过仅使用 @Bean
并删除 3 classes 上的 @Component
来允许对要实例化的 bean 进行完全控制:
@Configuration
public class MyConfiguration{
@Bean
public IndexUpdater getIndexUpdater(){
return new IndexDirectUpdater();
}
@Bean
public SearchIndexImpl getSearchIndexFoo(){
return new SearchIndexImpl(getIndexUpdater());
}