Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring ignoring @Qualifier in very simple program

Tags:

java

spring

I have Circle class:

public class Circle
{
    @Autowired
    @Qualifier("pointA")
    private Point center;

    public Point getCenter()
    {
        return center;
    }
    public void setCenter(Point center)
    {
        this.center = center;
    }
}

point class:

public class Point
{
    private int x;
    private int y;

    public int getX()
    {
        return x;
    }
    public void setX(int x)
    {
        this.x = x;
    }
    public int getY()
    {
        return y;
    }
    public void setY(int y)
    {
        this.y = y;
    }
}

And my 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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd"
        >

       <bean id="pointA"  name="pointA" class="SpringTest.Point">
            <qualifier value="pointA"/>
            <property name="x" value="4"/>
            <property name="y" value="4"/>
       </bean>

       <bean id="pointB" name="pointB" class="SpringTest.Point">
              <property name="x" value="2"/>
              <property name="y" value="5"/>
       </bean>

       <bean id="circle" class="SpringTest.Circle">
       </bean>

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

</beans>

As far as I am concerned this should work like this: 1. Spring see @Autowire annotation 2. Spring realizes that there are many beans of Point type 3. Spring uses @Qualifier annotation to determine which bean to inject

Unfortunaltely it is not working like that. While executing:

AbstractApplicationContext abstractApplicationContext = new ClassPathXmlApplicationContext("spring.xml");
BeanFactory beanFactory = abstractApplicationContext.getBeanFactory();

I am getting an error:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'circle': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private SpringTest.Point SpringTest.Circle.center; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [SpringTest.Point] is defined: expected single matching bean but found 2: pointA,pointB

I am beginner at spring topic but I believe @Qualifier annotation should do the job and determine which bean to use.

Startup log: https://gist.github.com/mmajews/384207ee97b2cc8bd49a

like image 388
Marcin Majewski Avatar asked Dec 15 '14 23:12

Marcin Majewski


People also ask

Can @bean and @qualifier used together?

NOTE: if you are creating bean with @Bean, it will be injected byType if there is duplicates then it will injected byName. we no need to mention @Bean(name="bmwDriver") . so you can directly use qualifier("bmwDriver") wherever you need in classes.

Why do we use @qualifier in Spring boot?

By using the @Qualifier annotation, we can eliminate the issue of which bean needs to be injected. By including the @Qualifier annotation, together with the name of the specific implementation we want to use, in this example Foo, we can avoid ambiguity when Spring finds multiple beans of the same type.

What is the difference between @primary and @qualifier in Spring?

Spring @Primary vs @Qualifier We use @Qualifier in Spring to autowire a specific bean among same type of beans, where as @Primary is used to give high preference to the specific bean among multiple beans of same type to inject to a bean.

What is the actual use of @autowired @qualifier @component annotation?

There may be a situation when you create more than one bean of the same type and want to wire only one of them with a property. In such cases, you can use the @Qualifier annotation along with @Autowired to remove the confusion by specifying which exact bean will be wired.


1 Answers

You need to add <context:annotation-config/> in your spring xml, rather than instantiating the AutowiredAnnotationBeanPostProcessor, as that does not handle @Qualifier annotations.

Or, if you really want to control everything that gets instantiated in your context, have a look at the actual candidate resolver for @Qualifier.

like image 67
Costi Ciudatu Avatar answered Nov 09 '22 02:11

Costi Ciudatu