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 ……这样的事情:
可能你的ApplicationContext
的BeanFactory
配置了默认的 AutowireCandidateResolver
(即SimpleAutowireCandidateResolver
)而不是QualifierAnnotationAutowireCandidateResolver
。
在Spring的 早期版本(4.0之前)中,在创建大多数ApplicationContexts期间设置了QualifierAnnotationAutowireCandidateResolver
(比较AbstractRefreshableApplicationContext.customizeBeanFactory(DefaultListableBeanFactory)
实现)。
目前,AppCtx的QualifierAnnotationAutowireCandidateResolver
可以通过以下方式应用:
-
org.springframework.beans.factory.annotation.CustomAutowireConfigurer
(参见javadoc和postProcessBeanFactory(ConfigurableListableBeanFactory)
方法的实现),例如添加到你的xml:org.springframework.beans.factory.annotation.Qualifier -
(参见: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定义: