【问题标题】:Spring 4.1 @Qualifier doesnt'workSpring 4.1 @Qualifier 不起作用
【发布时间】:2016-09-21 21:01:35
【问题描述】:

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

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);
}

}

测试类

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

需要帮助

【问题讨论】:

    标签: java spring autowired


    【解决方案1】:

    可能您的ApplicationContextBeanFactory 配置为默认 AutowireCandidateResolver(即SimpleAutowireCandidateResolver)而不是QualifierAnnotationAutowireCandidateResolver

    在以前的 Spring 版本(4.0 之前)中,QualifierAnnotationAutowireCandidateResolver 在大多数 ApplicationContexts 的创建期间设置(比较 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. &lt;context:annotation-config /&gt;(参见:AnnotationConfigBeanDefinitionParser.parse(Element,ParserContext) 及相关)

    【讨论】:

    • 非常好 - 对我从 3.2 到 4.3 的移植非常有帮助。由于我的@Autowire 已经被检测到(但由于未处理限定符而失败),我不需要添加 元素。
    • 这是答案!
    【解决方案2】:

    @Qualifier 用于通过名称或 id 引用 bean。由于它找不到名称或 id 为“small”的 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>
    

    【讨论】:

      【解决方案3】:

      @Qualifier(name="..") 注解并给出我们希望 Spring 注入的 bean 的名称

      你的豆子的名字是 size1 和 size2 。

      那就试试吧

         @Qualifier("size1")
      

      【讨论】:

        【解决方案4】:

        @Qualifier("small") 表示您查找名为“small”的 bean (bean id="small" ...) @Autowired 表示您查找类型匹配的 bean。

        在某些情况下将这两种配置一起使用是有意义的。它的意思是:寻找一个这样命名的bean,如果没有找到,则寻找一个具有正确类型的bean。这可以很强大,非常。

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

        来修复你的示例

        【讨论】:

          【解决方案5】:

          正如你的堆栈跟踪所说

          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 实例时抛出异常 当只有一个时找到了多个匹配的候选者 预期匹配 bean。

          Reference of Exception

          反正你用错了这个东西,因为没有id="small"的bean

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

          【讨论】:

            【解决方案6】:

            在 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

            【讨论】:

              【解决方案7】:

              在我们的项目中,我们将 struts 1.x 与 Spring 3.x 一起使用。在从spring 3->4升级的过程中,我们在struts action中的qualifier注解已经失效了。经过深挖对比Spring 3和4,终于找到原因了。

              原因1:QualifierAnnotationAutowireCandidateResolver 不是 spring 4 中的默认解析器

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

              beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
              

              在 spring 4 中,AbstractRefreshableApplicationContext 中不再调用它

              protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)
              

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

              原因 2:在 Spring 4 的 DefaultListableBeanFactory 中尝试确定“isAutowireCandidate()”时,子解析器被传递给父解析器

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

              在 Spring 3 中,委托不会将解析器传递给父级,因此父级上下文使用自己的解析器调用 isAutowireCandidate()。但是在 Spring 4 中,它发生了变化。解析器作为参数传递给使用它调用 isAutowireCandidate() 的父级。所以即使父母有一个 ContextAnnotationAutowireCandidateResolver 扩展 QualifierAnnotationAutowireCandidateResolver 作为它的解析器,它仍然没有帮助。

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

              【讨论】:

                【解决方案8】:

                尝试在您的 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>
                

                【讨论】:

                猜你喜欢
                • 2018-08-06
                • 1970-01-01
                • 2018-01-16
                • 2016-12-05
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-07-20
                相关资源
                最近更新 更多