为什么我在春天没有获得自动装配中没有类型的独特豆类

时间:2015-12-29 09:18:58

标签: java 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( );
    }

在上面的示例中,我使用Ability@Controller文件中的一个定义了xml第一类的两个bean。根据{{​​1}}类型我应该得到

Autowire

但我得到了正确的输出。为什么呢?

如果我创建一个Ability类实现的接口,那么我会得到UnsatisfiedDependencyException异常。像这样:

Parent.java

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

Ability.java

public interface Parent{

     public void printMessasge();

}

Person.java

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

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

3 个答案:

答案 0 :(得分:3)

默认情况下,Spring确实按类型匹配,但是在多个匹配bean的情况下,它会回退到按名称匹配。引用(6.9.4 Fine-tuning annotation-based autowiring with qualifiers)表示:

  

对于后备匹配,bean名称被视为默认限定符值。

使用@Qualifier注释可以按类型进行自动装配,另外还可以通过名称更加明确。

答案 1 :(得分:2)

你不会得到UnsatisfiedDependencyException这个配置,因为Spring足够智能,也可以查看所需依赖项的名称,正如@Adam在他的回答中写道的那样。因此,即使默认的自动装配模式是按类型,并且该依赖项有两个相同类型的bean,Spring也能够解决冲突。

官方文档6.9.4 Fine-tuning annotation-based autowiring with qualifiers部分介绍了此行为。 有关自动装配模式的更多详细信息,请参见6.4.5 Autowiring collaborators

如果您将Person.ability字段的名称更改为其他内容,例如Person.ability2,那么Spring将抛出org.springframework.beans.factory.NoUniqueBeanDefinitionException 。它无法决定应该为Person.ability2字段连接哪个bean,因为:

  1. 上下文中有两个com.mkyong.common.Ability类型的bean
  2. 字段名称与bean名称
  3. 不匹配

    编辑:在你提到的第二种情况下(使用界面),Spring抛出了我上面解释的相同bean命名原因的异常。

    官方文件参考:

答案 2 :(得分:0)

你定义了两个不明确的bean,当spring尝试通过类型找到bean时,它会找到两个bean,一个是通过扫描,另一个是在spring.xml中明确定义的。使用@Qualifier标记Person类中加载的正确bean。所以你可能想要这样,

 @Controller
public class Person 
{

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

     public void printMessage(){

         ability.printMessasge();
     }

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