Search code examples
javaspringdependency-injectionconstructor-injection

Bean is getting injected eventhough @Qualifier value is not matched in Constructor Injection


I'm trying constructor injection using @Autowired and @Qualifier in Spring 5.

    public class A {

    private int a;

    public void setA(int a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return "A [a=" + a + "]";
    }
}

Class Hello

    public class Hello {

    private A aobj;

    @Autowired
    public Hello(@Qualifier("a01") A aobj) {
        this.aobj = aobj;
    }

    public void show() {
        System.out.println("aobj : " + aobj);
    }
}

Config Class

    @Configuration
public class JavaConfig {

    @Bean(name = "a02")
    public A createA1() {
        A ob = new A();
        ob.setA(199);
        return ob;
    }

    @Bean
    public Hello hello(A aobj) {
        return new Hello(aobj);
    }
}

Main Class

public static void main(String[] args) {

    ApplicationContext ctx = new AnnotationConfigApplicationContext(JavaConfig.class);
    System.out.println("--------Spring Container is ready----------");  
    Hello hello = (Hello)ctx.getBean("hello");
    hello.show();
}

Output:

--------Spring Container is ready----------
aobj : A [a=199]

Intentionally, I'm giving wrong value(a02) for Bean name in Config Class which is not same as @Qualifier value(a01) in Hello Class.

As a result of that What I'm observing Bean A is getting injected in Hello Bean successfully.

Ideally It should through error, because in container no expected matching bean named a01 found, otherwise what is the use of @Qualifier in that use case.

Could someone put light on that. Thanks!!


Solution

  • The problem here is that you aren't using autowiring when creating your Hello bean! Instead, you're writing your own factory method hello and calling the constructor directly yourself. @Qualifier is a note that the container reads when it's instantiating the class, not some kind of validation that's baked into the constructor itself (like some tools can do with @Nonnull).

    If you need to continue using @Bean, then you'll need to apply the @Qualifier to the method parameter. Even simpler, just apply @Import(Hello.class) to your JavaConfig and let Spring sort this out for you.