简体   繁体   中英

Why i am not getting No unique bean of type in Autowiring in spring

Person.java

@Controller
public class Person 
{
    @Autowired
    private Ability ability;

     public void printMessage(){

         ability.printMessasge();
     }

     public void setOutputGenerator( Ability ability) {
            this.ability = ability;
        }  
}

Ability.java

@Controller
public class Ability 
{
     void printMessasge(){

         System.out.println("I print message");
     }

}

spring.xml

<bean id="invisible" class="com.mkyong.common.Ability" >
</bean>  

<context:component-scan base-package="com.mkyong" /> 

App.java

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext(
                "spring.xml");

        Person person = (Person) context.getBean("person");
        person.printMessage( );
    }

In the above example i have defined two beans of Ability class one using @Controller and one in xml file. According to Autowire by type i should get

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: 
...
No unique bean of type [com.mkyong.common.Ability] is defined:

But i am getting proper output. Why?

And if i create an interface which Ability class implements then i would get UnsatisfiedDependencyException exception. Like this:

Parent.java

public interface Parent{

     public void printMessasge();

}

Ability.java

@Controller
public class Ability implements Parent
{
      void printMessasge(){

         System.out.println("I print message");
     } 

Person.java

@Controller
public class Person 
{
    @Autowired
    Parent parent;
     public void printMessage(){
         parent.printMessasge();
     }

     public void setOutputGenerator( Parent parent) {
            this.parent= parent;
        }  
}

By default Spring indeed matches by type, but in case of multiple matching beans, it falls back to matching by name. The reference ( 6.9.4 Fine-tuning annotation-based autowiring with qualifiers ) says:

For a fallback match, the bean name is considered a default qualifier value.

Using the @Qualifier annotation makes the autowiring by type and additionally by name more explicit.

You are not going to get a UnsatisfiedDependencyException with this configuration because Spring is smart enough to also look at the name of your required dependency, as @Adam writes in his answer. So even if the default autowiring mode is by type and there are two beans of the same type for that dependency, Spring is able to solve the conflict.

This behavior is described in the official documentation, 6.9.4 Fine-tuning annotation-based autowiring with qualifiers section. More details about autowiring modes can be found 6.4.5 Autowiring collaborators .

If you change the name of Person.ability field to something else, like Person.ability2, then Spring will throw a org.springframework.beans.factory.NoUniqueBeanDefinitionException . It cannot decide which bean it should wire for the Person.ability2 field because:

  1. There are two beans of com.mkyong.common.Ability type in the context
  2. Field name does not match with either bean names

EDIT: in the second case you mention (with the interface), Spring throws the exception for the same bean naming reason I explained above.


Official documentation references:

you have two ambiguous beans defined, when spring try find the bean via type it finds two beans, one via scan other explicitly defined in spring.xml. use @Qualifier to mark the correct bean loaded in Person class. So probably you want like this,

 @Controller
public class Person 
{

      @Autowired
      @Qualifier("invisible")
      private Ability ability;

     public void printMessage(){

         ability.printMessasge();
     }

     public void setOutputGenerator( Ability ability) {
            this.ability = ability;
        }  
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM