Reputation: 887
I have an interface Animal
having two implementations Cat
and Dog
. These two implementations are spring @Component
. How do I conditionally wire these two based on a value? I understand that I may have to change the scope of MyTestController from singleton to request.
@RestController
public class MyTestController {
@Autowired
Animal animal;// how to wire bean of Cat or Dog based on animalName
@PostMapping("/get-animal")
public @ResponseBody Animal getAnimal(@RequestParam(value = "animalName") String animalName) {
return animal;
}
}
Upvotes: 0
Views: 628
Reputation: 844
Since both MyTestController
is a bean the autowiring / initialisation happens before you actually start using the class instance itself. What I mean is that by the time you actually trigger REST requests on your controller, the injected animal
bean should be already there!
More specifically if you have two classes that implement the same interface (Animal
) without further specification (active Profiles, or @Primary
annotation) Spring won't be able to decide which implementation to inject while creating the MyTestController
,
What you want to do is return beans from your ApplicationContext
based on a parameter / class name. This would look something like this:
@Autowired
private ApplicationContext context;
/* ... */
if(animalName.equals("dog") {
context.getBean(Dog.class) //returning the dog bean
} else if(animalName.equals("cat") {
context.getBean(Cat.class) //returning the cat bean
}
Edit IMO the question is a bit confusing. You ask for wiring the bean based on a value, but this value only comes at runtime. Hence my answer. However If you want to wire based on some variable at initialisation of your bean I would suggest taking a look at the following sources:
Finally I would note that such an inversion on the IoC is considered as a bad practice. (See here)
Upvotes: 1
Reputation: 6620
Well, you're missing the whole point. Don't autowire simple DTO, but autowire AnimalFactory or some kind of AnimalRepository (or better - Service) where you can create or retrieve animals based on animal type.
It would look something like that:
@Component
public class AnimalFactory {
public Animal createAnimal(String animalType) {
switch (animalType) {
case "DOG":
return new Dog();
case "CAT":
return new Cat();
}
throw new IllegalArgumentException("AnimalType is invalid");
}
}
Animal Spring Data JPA Repository:
@Component
public class AnimalRepository implements JpaRepository<Animal, Long> {
public Optional<Animal> findByAnimalName(String animalName);
}
Upvotes: 0