В платформе Java EE с CDI есть возможность вводить экземпляры классов POJO. Очень простым способом нам нужно использовать аннотацию @Inject, чтобы ввести экземпляр по умолчанию для какого-либо интерфейса. Мы также можем использовать квалификаторы для ввода конкретного класса в наше поле. Но эти решения довольно статичны.Динамические инъекции экземпляров через CDI
Мне нужна еще одна динамическая модель инъекционного материала.
Позвольте мне представить мою проблему: Предположим, что у нас есть интерфейс Animal и три класса, которые реализуют этот интерфейс: Ant, Dog, Elephant. Я хотел бы динамически вставлять экземпляр одного из этих трех классов, и это зависит от некоторой переменной, такой как строка (имя животного). В Java SE Я хотел бы сделать это, как показано ниже:
Map<String, Animal> animalMap = new HashMap<>();
animalMap.put("ant", new Ant());
animalMap.put("dog", new Dog());
animalMap.put("elephant", new Elephant());
...
String animalName = ...;
Animal animal = animalMap.get(animalMap);
animal.doSomething();
Так что мне нужно что-то вроде:
class AnimalManager {
@Inject // ?
private Animal animal; // ?
public void run(String animalName) {
// based on animalName get new instance of animal and run doSomething()
...
animal.doSomething(); // if animalName is "ant" call the doSomething on Ant class
}
}
Во всех классов, которые реализуют интерфейс Animal Мне нужно использовать переменные с @EJB аннотациями.
Какой лучший и самый правильный способ сделать это в Java EE?
EDIT:
OK на основе ответа от Svetlin Зарев и hwellmann Я создал это (спасибо!):
В начале мы создадим модель животных:
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE})
public @interface AnimalModel {
Type value();
enum Type { ANT, DOG, ELEPHANT }
}
Давайте создадим животное :
public interface Animal {
public void eat(Object food);
}
Следующая, конкретные классы:
@AnimalModel(AnimalModel.Type.ANT)
public class Ant implements Animal {
@Override
public void eat(Object food) {
...
}
}
@AnimalModel(AnimalModel.Type.DOG)
public class Dog implements Animal {
@Override
public void eat(Object food) {
...
}
}
@AnimalModel(AnimalModel.Type.ELEPHANT)
public class Elephant implements Animal {
@Override
public void eat(Object food) {
...
}
}
Далее AnimalLiteral:
public class AnimalLiteral extends AnnotationLiteral<AnimalModel> implements AnimalModel {
private static final long serialVersionUID = 1L;
private Type type;
public AnimalLiteral(Type type) {
this.type = type;
}
public Type value() {
return type;
}
}
Основным компонентом является животное завода:
@Dependent
public class AnimalFactory {
@Inject
@Any
private Instance<Animal> animals;
private static Map<String, AnimalModel.Type> animalMap;
public AnimalFactory() {
animalMap = new HashMap<>();
animalMap.put("ant", AnimalModel.Type.ANT);
animalMap.put("dog", AnimalModel.Type.DOG);
animalMap.put("elephant", AnimalModel.Type.ELEPHANT);
}
public Animal getAnimal(String animalName) {
AnimalModel.Type type = animalMap.get(animalName);
AnimalLiteral literal = new AnimalLiteral(type);
Instance<Animal> animalInstance = animals.select(literal);
return animalInstance.get();
}
}
И клиент:
public class Client {
@Inject
private AnimalFactory animalFactory;
public void run(String animalName) {
Animal animal = animalFactory.getAnimal(animalName);
animal.eat("some food...");
}
}
Я не знаю, что положить карту animalMap в этом месте правильно ...?
Использовать инъекцию конструктора вместо инъекции в поле. – chrylis