简体   繁体   English

为什么我在春季没有自动布线中没有类型独特的bean

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

Person.java 人.java

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

     public void printMessage(){

         ability.printMessasge();
     }

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

Ability.java Ability.java

@Controller
public class Ability 
{
     void printMessasge(){

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

}

spring.xml spring.xml

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

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

App.java 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. 在上面的示例中,我定义了两个Ability类的bean,一个使用@Controller ,另一个在xml文件中。 According to Autowire by type i should get 根据Autowire的类型,我应该得到

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. 如果我创建一个由Ability类实现的接口,那么我将得到UnsatisfiedDependencyException异常。 Like this: 像这样:

Parent.java Parent.java

public interface Parent{

     public void printMessasge();

}

Ability.java Ability.java

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

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

Person.java 人.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. 默认情况下,Spring确实按类型进行匹配,但是如果有多个匹配的Bean,它将回退到按名称进行匹配。 The reference ( 6.9.4 Fine-tuning annotation-based autowiring with qualifiers ) says: 参考资料( 6.9.4使用限定符微调基于注释的自动装配 )表示:

For a fallback match, the bean name is considered a default qualifier value. 对于后备匹配,bean名称被认为是默认的限定符值。

Using the @Qualifier annotation makes the autowiring by type and additionally by name more explicit. 使用@Qualifier批注使按类型以及名称的自动装配更加明确。

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. 这种配置不会导致UnsatisfiedDependencyException ,因为Spring非常聪明,还可以查看所需依赖项的名称,就像@Adam在他的回答中所写的那样。 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. 因此,即使默认的自动装配模式是按类型,并且对于该依赖项有两个相同类型的bean,Spring也能够解决冲突。

This behavior is described in the official documentation, 6.9.4 Fine-tuning annotation-based autowiring with qualifiers section. 官方文档6.9.4中的“使用限定符对基于注释的自动装配进行微调”部分对此行为进行了描述。 More details about autowiring modes can be found 6.4.5 Autowiring collaborators . 有关自动装配模式的更多详细信息,请参见6.4.5自动装配协作器

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 . 如果将Person.ability字段的名称更改为其他名称,例如Person.ability2,那么Spring将抛出org.springframework.beans.factory.NoUniqueBeanDefinitionException It cannot decide which bean it should wire for the Person.ability2 field because: 它不能决定应为Person.ability2字段连接哪个bean,因为:

  1. There are two beans of com.mkyong.common.Ability type in the context 上下文中有com.mkyong.common.Ability类型的两个bean
  2. Field name does not match with either bean names 字段名称与任何一个bean名称都不匹配

EDIT: in the second case you mention (with the interface), Spring throws the exception for the same bean naming reason I explained above. 编辑:在第二种情况下,您提到(使用接口),Spring会出于与我上面解释的相同的bean命名原因而引发异常。


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. 您定义了两个模糊的be​​an,当spring尝试通过类型查找bean时,它会找到两个bean,一个通过scan其他在spring.xml中显式定义的bean。 use @Qualifier to mark the correct bean loaded in Person class. 使用@Qualifier标记在Person类中加载的正确bean。 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;
        }  
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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