spring autowiring with unique beans: Spring expected single matching bean but found 2

后端 未结 4 1069
滥情空心
滥情空心 2020-11-30 01:06

I am trying to autowire some beans (for dependency injection) using Spring for a webapp. One controller bean contains another bean which in turn holds a hashmap of another

相关标签:
4条回答
  • 2020-11-30 01:35

    If I'm not mistaken, the default bean name of a bean declared with @Component is the name of its class its first letter in lower-case. This means that

    @Component
    public class SuggestionService {
    

    declares a bean of type SuggestionService, and of name suggestionService. It's equivalent to

    @Component("suggestionService")
    public class SuggestionService {
    

    or to

    <bean id="suggestionService" .../>
    

    You're redefining another bean of the same type, but with a different name, in the XML:

    <bean id="SuggestionService" class="com.hp.it.km.search.web.suggestion.SuggestionService">
        ...
    </bean>
    

    So, either specify the name of the bean in the annotation to be SuggestionService, or use the ID suggestionService in the XML (don't forget to also modify the <ref> element, or to remove it, since it isn't needed). In this case, the XML definition will override the annotation definition.

    0 讨论(0)
  • 2020-11-30 01:39

    The issue is because you have a bean of type SuggestionService created through @Component annotation and also through the XML config . As explained by JB Nizet, this will lead to the creation of a bean with name 'suggestionService' created via @Component and another with name 'SuggestionService' created through XML .

    When you refer SuggestionService by @Autowired, in your controller, Spring autowires "by type" by default and find two beans of type 'SuggestionService'

    You could do the following

    1. Remove @Component from your Service and depend on mapping via XML - Easiest

    2. Remove SuggestionService from XML and autowire the dependencies - use util:map to inject the indexSearchers map.

    3. Use @Resource instead of @Autowired to pick the bean by its name .

       @Resource(name="suggestionService")
       private SuggestionService service;
      

    or

        @Resource(name="SuggestionService")
        private SuggestionService service;
    

    both should work.The third is a dirty fix and it's best to resolve the bean conflict through other ways.

    0 讨论(0)
  • 2020-11-30 01:40

    For me it was case of having two beans implementing the same interface. One was a fake ban for the sake of unit test which was conflicting with original bean. If we use

    @component("suggestionServicefake")

    , it still references with suggestionService. So I removed @component and only used

    @Qualifier("suggestionServicefake")

    which solved the problem

    0 讨论(0)
  • 2020-11-30 01:52

    If you have 2 beans of the same class autowired to one class you shoud use @Qualifier (Spring Autowiring @Qualifier example).

    But it seems like your problem comes from incorrect Java Syntax.

    Your object should start with lower case letter

    SuggestionService suggestion;
    

    Your setter should start with lower case as well and object name should be with Upper case

    public void setSuggestion(final Suggestion suggestion) {
        this.suggestion = suggestion;
    }
    
    0 讨论(0)
提交回复
热议问题