Spring 4.1 @Qualifier没有工作

我有这样的类,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

                  

错误堆栈跟踪

 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.(FileSystemXmlApplicationContext.java:140) at org.springframework.context.support.FileSystemXmlApplicationContext.(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.(FileSystemXmlApplicationContext.java:140) at org.springframework.context.support.FileSystemXmlApplicationContext.(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 

需要帮忙

@Qualifier用于通过名称或id引用bean。 由于找不到名称或id为“small”的xml条目,因此它尝试按类型进行匹配,并找到两个Size实例。

以下方法可行:

      

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

      

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

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

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

  1. org.springframework.beans.factory.annotation.CustomAutowireConfigurer (参见javadoc和postProcessBeanFactory(ConfigurableListableBeanFactory)方法的实现),例如添加到你的xml:

        org.springframework.beans.factory.annotation.Qualifier   

  2. (参见: AnnotationConfigBeanDefinitionParser.parse(Element,ParserContext)及相关)

@Qualifier(name =“..”)注释,并给出我们希望Spring注入的bean的名称

您的bean的名称是size1和size2。

所以试试吧

  @Qualifier("size1") 

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

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

从Spring文档中 ,您可以像使用xml限定符一样声明谁是“小”。 但在他们的例子中有NO id =“…”我不知道定义限定符和id是否有意义。 所以我想(我不测试)你可以删除部件id =“sizeX”来修复你的例子

如你所说的堆栈跟踪

 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,因此会抛出此exception。

当BeanFactory被要求提供一个bean实例时抛出exception,当只有一个匹配的bean被预期时,找到了多个匹配的候选者。

参考例外

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

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

在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" 

你应该添加以下标记:

  

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

                  

在这里查看更多。

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

reason1:QualifierAnnotationAutowireCandidateResolver不是spring 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中,它应该可以正常工作。

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