Spring 4.1 @Qualifier不起作用

时间:2014-10-17 13:58:07

标签: java spring autowired

我有这样的类,xml配置文件和错误堆栈跟踪。我不知道为什么@Qualifier不起作用。我看到错误,他甚至做不了什么。

DOG

public class SimpleDog implements Dog {
    @Autowired
    @Qualifier("small")
    private Size size;
    private String name;

public Size getSize() {
    return size;
}

public void setSize(Size size) {
    this.size = size;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@Override
public void giveSound() {
    System.out.println("dog size is : width : (" + size.getWidth() + ") , height : (" + size.getHeight() + ")");
    System.out.println("dog's name : " + name);
}

}

TEST CLASS

public class Test2 {
public static void main(String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("spring-test2.xml");
    SimpleDog dog = (SimpleDog) context.getBean("dog");
    dog.giveSound();
}

}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dog" class="com.tests.test2.SimpleDog">
         <property name="name" value="Puppy" />
    </bean>

    <bean id="size1" class="com.tests.test2.Size">
        <qualifier value="small"/>
        <property name="height" value="2"/>
        <property name="width" value="1"/>
    </bean>

    <bean id="size2" class="com.tests.test2.Size">
        <qualifier value="large"/>
        <property name="height" value="20"/>
        <property name="width" value="10"/>
    </bean>

    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
</beans>

错误堆栈跟踪

WARNING: Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dog': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
    at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
    at pl.patrykgryta.test2.Test2.main(Test2.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 18 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1016)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
    ... 20 more

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dog': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1204)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:229)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:725)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:757)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
    at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:140)
    at org.springframework.context.support.FileSystemXmlApplicationContext.<init>(FileSystemXmlApplicationContext.java:84)
    at pl.patrykgryta.test2.Test2.main(Test2.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.tests.test2.Size com.tests.test2.SimpleDog.size; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 18 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1016)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:904)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:527)
    ... 20 more

需要帮助

8 个答案:

答案 0 :(得分:10)

可能您的ApplicationContext BeanFactory配置了默认 AutowireCandidateResolver(即SimpleAutowireCandidateResolver)而不是QualifierAnnotationAutowireCandidateResolver }。

在以前版本的 Spring (4.0之前)中,在创建大多数ApplicationContexts(比较QualifierAnnotationAutowireCandidateResolver实现)期间设置了AbstractRefreshableApplicationContext.customizeBeanFactory(DefaultListableBeanFactory)

目前,AppCtx的QualifierAnnotationAutowireCandidateResolver可以通过以下方式应用:

  1. org.springframework.beans.factory.annotation.CustomAutowireConfigurer (请参阅javadoc和postProcessBeanFactory(ConfigurableListableBeanFactory)方法的实施),例如添加到您的xml:

    <bean id="customAutowireConfigurer" class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>org.springframework.beans.factory.annotation.Qualifier</value>
        </set>
    </property>
    

  2. <context:annotation-config /> (请参阅:AnnotationConfigBeanDefinitionParser.parse(Element,ParserContext)及相关的)

答案 1 :(得分:4)

@Qualifier用于通过名称或id引用bean。因为它无法找到名称或ID为&#39;小&#39;的xml条目。它尝试按类型进行匹配,它找到了两个Size实例。

以下方法可行:

  <bean id="small" class="com.tests.test2.Size">      
    <property name="height" value="2"/>
    <property name="width" value="1"/>
</bean>

虽然看起来您希望将Size实例视为预先配置的bean。如果是这种情况你可以在你的xml文件中声明Dog的实例并引用Size beans ......就像这样:

  <bean id="rex" class="com.tests.test2.SimpleDog">
     <property name="name" value="Puppy" />
     <property name="size" ref="size1"/>
  </bean>

答案 2 :(得分:2)

@Qualifier(name =&#34; ..&#34;)注释,并给出我们希望Spring注入的bean的名称

并且您的bean的名称是size1和size2。

所以试试

   @Qualifier("size1")

答案 3 :(得分:2)

@Qualifier(“small”)意味着你要找一个名为“small”的bean(bean id =“small”......)@Autowired意味着你要找一个匹配类型的bean。

在某些情况下,将这两种配置结合使用是有意义的。这意味着:寻找一个名为that的bean,如果找不到,那么找一个具有正确类型的bean。这非常强大。

Spring documentation开始,您可以像使用xml限定符一样声明谁是“小”。但是在他们的例子中有NO id =“...”我不知道定义限定符和id是否有意义。所以我想(我不测试)你可以通过删除部分id =“sizeX”

来修复你的例子

答案 4 :(得分:1)

正如您所说的堆栈跟踪

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.tests.test2.Size] is defined: expected single matching bean but found 2: size1,size2

Spring无法匹配单个bean来注入,因为他找到了2个可以使用的bean,因此会抛出此异常。

  

当向BeanFactory请求bean实例时抛出异常   当只有一个时,找到了多个匹配的候选者   期待匹配的豆。

Reference of Exception

无论如何你以错误的方式使用这个东西,因为没有id="small"

的bean

您必须将@Qualifier("small")更改为@Qualifier("size1")@Qualifier("size2")

答案 5 :(得分:1)

在Spring 4.x中,您应该使用以下XML架构,以便它可以为您服务:

xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"

您应该添加以下标记:

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

所以下面的XML应该可以解决你的问题(它解决了我的问题:)):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

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

    <bean id="dog" class="com.tests.test2.SimpleDog">
       <property name="name" value="Puppy" />
    </bean>

    <bean id="size1" class="com.tests.test2.Size">
        <qualifier value="small"/>
        <property name="height" value="2"/>
        <property name="width" value="1"/>
    </bean>

    <bean id="size2" class="com.tests.test2.Size">
        <qualifier value="large"/>
        <property name="height" value="20"/>
        <property name="width" value="10"/>
    </bean>
</beans>

查看更多here

答案 6 :(得分:0)

我们的项目中使用了Spring 3.x的struts 1.x.在从spring 3&gt; 4升级的过程中,我们在struts动作中的限定符注释不再起作用。在深入挖掘并比较Spring 3和4之后,终于找到了原因。

reason1:QualifierAnnotationAutowireCandidateResolver不是春季4的默认解析器

在Spring 3中,在我们在应用程序上下文中创建beanfacotry之后,Spring将显式调用:

beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());

在Spring 4中,在AbstractRefreshableApplicationContext的

中不再调用它
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)

因此对于父(root)上下文,如果你在config xml中有它,它应该仍然可以工作。但是对于子上下文,默认解析器将变为“SimpleAutowireCandidateResolver”

reason2:在Spring 4的DefaultListableBeanFactory

中尝试确定'isAutowireCandidate()'时,子解析器被传递给父级

如果无法做出决定,isAutowireCandidate()会将责任委托给父beanFactory。

在Spring 3中,委托不会将解析器传递给父级,以便父上下文使用自己的解析器来调用isAutowireCandidate()。然而在春季4,它发生了变化。解析器作为参数传递给使用它来调用isAutowireCandidate()的父级。因此,即使父母有一个ContextAnnotationAutowireCandidateResolver,它将QualifierAnnotationAutowireCandidateResolver扩展为其解析器,它仍然无济于事。

如果将@ a5phyx解决方案添加到 的应用程序上下文xml中,它应该可以正常工作。

答案 7 :(得分:0)

尝试在beans.xml文件中使用此bean定义:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd"
        xmlns:context="http://www.springframework.org/schema/context">

    <context:annotation-config/>
    <!-- define your beans here-->
</beans>