Spring choose bean implementation at runtime

后端 未结 5 1200
我寻月下人不归
我寻月下人不归 2020-11-29 21:23

I\'m using Spring Beans with annotations and I need to choose different implementation at runtime.

@Service
public class MyService {
   public void test(){..         


        
5条回答
  •  情深已故
    2020-11-29 21:54

    Let's create beautiful config.

    Imagine that we have Animal interface and we have Dog and Cat implementation. We want to write write:

    @Autowired
    Animal animal;
    

    but which implementation should we return?

    So what is solution? There are many ways to solve problem. I will write how to use @Qualifier and Custom Conditions together.

    So First off all let's create our custom annotation:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
    public @interface AnimalType {
        String value() default "";
    }
    

    and config:

    @Configuration
    @EnableAutoConfiguration
    @ComponentScan
    public class AnimalFactoryConfig {
    
        @Bean(name = "AnimalBean")
        @AnimalType("Dog")
        @Conditional(AnimalCondition.class)
        public Animal getDog() {
            return new Dog();
        }
    
        @Bean(name = "AnimalBean")
        @AnimalType("Cat")
        @Conditional(AnimalCondition.class)
        public Animal getCat() {
            return new Cat();
        }
    
    }
    

    Note our bean name is AnimalBean. why do we need this bean? because when we inject Animal interface we will write just @Qualifier("AnimalBean")

    Also we crated custom annotation to pass the value to our custom Condition.

    Now our conditions look like this (imagine that "Dog" name comes from config file or JVM parameter or...)

       public class AnimalCondition implements Condition {
    
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            if (annotatedTypeMetadata.isAnnotated(AnimalType.class.getCanonicalName())){
               return annotatedTypeMetadata.getAnnotationAttributes(AnimalType.class.getCanonicalName())
                       .entrySet().stream().anyMatch(f -> f.getValue().equals("Dog"));
            }
            return false;
        }
    }
    

    and finally injection:

    @Qualifier("AnimalBean")
    @Autowired
    Animal animal;
    

提交回复
热议问题