spring

Using @Qualifier and @Bean together in Java Config Spring


I have follow code

interface Drivable {

}

@Component
class Bmw implements Drivable {

}

@Component
class Mercedes implements Drivable {

}

class Driver {
    private Drivable drivable;

    public Driver(Drivable drivable) {
        this.drivable = drivable;
    }
}

And Spring Java Config

@Configuration
@ComponentScan
class CarConfig {
    @Bean
    @Qualifier("mercedes")//the code won't work
    public Driver getDriver(Drivable drivable) {
        return new Driver(drivable);
    }

    @Bean//I've added the bean
    public Drivable getMercedes() {
        return new Mercedes();
    }
}

Can I use @Qualifier annotation with @Bean annotation if I want to specify type of object that should pass to method? I can't find in Spring doc how I can solve the problem. Thx.


Solution

  • I think you got the usage of @Qualifier bit wrong.

    If we have more than one bean that qualifies for spring injection, then we use @Qualifer to specify which needs to be used for injection.

    In this case you have two beans Bmw and Mercedes both implementing Drivable interface.

    Presuming I got your intent correct, you want spring to inject Mercedes bean into the Driver object.

    So for that, you need to specify public Driver getDriver(@Qualifier("mercedes") Drivable drivable) in the CarConfig class.

    @Configuration
    @ComponentScan
    class CarConfig {
        @Bean
        public Driver getDriver(@Qualifier("mercedes") Drivable drivable) {
            return new Driver(drivable);
        }
    

    And then you can use AnnotationConfigApplicationContext to load the spring context and subsequently get the Driver bean as below:

        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CarConfig.class);
            Driver bean = ctx.getBean(Driver.class);
        }
    }
    

    Just to extend the example, let us say if you want to create a Driver bean for each of Bmw and Mercedes then the sample code would be:

    @Configuration
    @ComponentScan
    class CarConfig {
        @Bean(name="mercedesDriver")
        public Driver getMercedesDriver(@Qualifier("mercedes") Drivable drivable) {
            return new Driver(drivable);
        }
    
        @Bean(name="bmwDriver")
        public Driver getBmwDriver(@Qualifier("bmw") Drivable drivable) {
            return new Driver(drivable);
        }
    
        public static void main(String[] args) {
            AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(CarConfig.class);
            System.out.println(Arrays.asList(ctx.getBeanNamesForType(Driver.class)));
            Driver mercedesBean = ctx.getBean("mercedesDriver", Driver.class);
            Driver bmwBean = ctx.getBean("bmwDriver", Driver.class);
        }
    }