如何为AutoWired Bean指定子依赖关系

时间:2019-07-04 20:16:08

标签: java spring spring-annotations spring-bean

我有一个这样定义的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批注做同样的事情?

1 个答案:

答案 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());
}