I have classes, xml configuration file and error stack trace like this. I have no idea why @Qualifier doesn\'t work. I see on errors that he don\'t even do anything.
In Spring 4.x you should work with the following XML schema in order for this to work for you:
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"
and you should add the following tag:
<context:component-scan base-package="com.tests.test2" />
So the following XML should solve your problem (it solved mine :) ):
<?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>
See more here.
Probably your ApplicationContext
's BeanFactory
is configured with default AutowireCandidateResolver
(i.e. SimpleAutowireCandidateResolver
) instead of QualifierAnnotationAutowireCandidateResolver
.
In previous versions of Spring (before 4.0), QualifierAnnotationAutowireCandidateResolver
was set during creation of most ApplicationContexts (compare AbstractRefreshableApplicationContext.customizeBeanFactory(DefaultListableBeanFactory)
implementations).
Currently, QualifierAnnotationAutowireCandidateResolver
for AppCtx is/can be applied by:
org.springframework.beans.factory.annotation.CustomAutowireConfigurer
(see javadoc and implementation of postProcessBeanFactory(ConfigurableListableBeanFactory)
method), e.g. add to your 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>
<context:annotation-config />
(see: AnnotationConfigBeanDefinitionParser.parse(Element,ParserContext)
and related)
As says your stacktrace
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 can't match a single bean to inject because he find 2 beans that could using, for this reason will thrown this exception.
Exception thrown when a BeanFactory is asked for a bean instance for which multiple matching candidates have been found when only one matching bean was expected.
Reference of Exception
Anyway you're using this thing in the wrong way, because there isn't any bean with id="small"
You must change @Qualifier("small")
to @Qualifier("size1")
or @Qualifier("size2")
.
We have struts 1.x used with Spring 3.x in our project. In the process of upgrading from spring 3->4, our qualifier annotation in the struts action does not work any more. After digging in and compare the Spring 3 and 4, finally found the reason.
reason1: QualifierAnnotationAutowireCandidateResolver is not the default resolver in spring 4
In Spring 3, after we create our beanfacotry in the application context, Spring will explicitly call :
beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
In spring 4, it is not called any more in the AbstractRefreshableApplicationContext’s
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory)
So for the parent(root) context, it should still work as is if you have the in the config xml. However for the child context the default resolver will become ‘SimpleAutowireCandidateResolver’
reason2: The child resolver is passed to parent when trying to determine ‘isAutowireCandidate()’ in Spring 4’s DefaultListableBeanFactory
The isAutowireCandidate() will delegate the responsibility to parent beanFactory if it cannot make decision.
In Spring 3, the delegation does not pass the resolver to the parent so that parent context uses its own resolver to call the isAutowireCandidate(). However in Spring 4, it changes. The resolver is passed as a parameter to the parent who uses it to call the isAutowireCandidate(). So even the parent has a ContextAnnotationAutowireCandidateResolver which extends QualifierAnnotationAutowireCandidateResolver as its resolver, it still does not help.
The @a5phyx solution should work if it is added to the child's application context xml.
Try using this bean definition in your beans.xml file:
<?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>
@Qualifier("small") means you look for a bean named "small" (bean id="small" ...) @Autowired means you look for a bean with a type that matchs.
It makes sense to use this two configurations together in some cases. It means: look for a bean named like that, and if you don't find, then look for a bean with the correct type. This can be powerful, very.
From the Spring documentation, you can declare who is "small" with an xml qualifier, as you did. But in their example there is NO id="..." I don't know if it makes sense to define both qualifier and id. So I suppose (I don't test) you can repair your example by removing the parts id="sizeX"