Using @Qualifier and @Bean together in Java Config Spring

后端 未结 2 2058
梦毁少年i
梦毁少年i 2021-01-05 19:31

I have follow code

   interface Drivable{

}

@Component
class Bmw implements Drivable {

}

@Component
class Mercedes implements Drivable {

}

class Driver         


        
相关标签:
2条回答
  • 2021-01-05 19:58

    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);
        }
    }
    
    0 讨论(0)
  • 2021-01-05 20:00

    You could define qualifiers for each specific implementations of interface Drivable. Once you did, now you could autowire them into CarConfig class and you have to be create Beans for each Drivers(Mercedz & Benz) along with qualifier names.

    Find below Implementation:

     @Target({ElementType.FIELD, ElementType.PARAMETER})
     @Retention(RetentionPolicy.RUNTIME)
     @Qualifier
     public @interface Bmw {
     }
    
     @Target({ElementType.FIELD, ElementType.PARAMETER})
     @Retention(RetentionPolicy.RUNTIME)
     @Qualifier
     public @interface Mercedes {
     }
    

    Now your Interface Implementations of Driver should be annotated with Qualifiers as below

    @Compoenent
    @Bmw
    public interface Bmw implements Drivable{
    }
    
    @Component
    @Mercedes
    public interface Mercedes implements Drivable{
    }
    

    Your CarConfig class should be as below:

    @Configuration
    public class CarConfig{
    
    @autowire
    @Bmw
    private Drivable bmwDriver;
    
    @autowire
    @Mercedes
    private Drivable mercedesDriver;
    
    
    @Bean
    public Bean getBmwDriver(){
      return new Bmw(bmwDriver);
      }
    
     @Bean
    public Bean getMercedesDriver(){
       return new Mercedes(mercedesDriver);
      }
    
     }
    

    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.

    0 讨论(0)
提交回复
热议问题