gpt4 book ai didi

java - 通过 CDI 动态注入(inject)实例

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:46:27 24 4
gpt4 key购买 nike

在带有 CDI 的 Java EE 平台中,可以注入(inject) POJO 类的实例。以非常简单的方式,我们需要使用@Inject 注释来注入(inject)某个接口(interface)的默认实例。我们也可以使用限定符将具体类注入(inject)我们的领域。但这些解决方案是相当静态的。

我需要一些更动态的注入(inject)东西模型。

介绍一下我的问题:假设我们有接口(interface) Animal 和实现该接口(interface)的三个类:Ant、Dog、Elephant。我想动态注入(inject)这三个类之一的实例,它取决于一些变量,如字符串(动物名称)。在 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 接口(interface)的类中,我需要使用带有@EJB 注释的变量。

在 Java EE 中最好和最合适的方法是什么?

编辑:
好的,基于 Svetlin Zarev 和 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...");
}

}

我不知道把 map animalMap放在那个地方是对的...?

最佳答案

使用 Instance<T>结合限定符是 CDI 中执行动态注入(inject)的标准方式。

您需要一个带有绑定(bind)参数的限定符,例如@Species("ant")区分您的实现类。

public class AnimalSelector {

@Inject
@Any
private Instance<Animal> animals;

public Animal selectAnimalBySpecies(String speciesName) {
SpeciesLiteral qualifier = new SpeciesLiteral(speciesName);
return animals.select(qualifier).get();
}
}

public class SpeciesLiteral extends AnnotationLiteral<Species> implements Species {

private String name;

public SpeciesLiteral(String name) {
this.name = name;
}

@Override
public String value() {
return name;
}
}

@Qualifier
@Target({ TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
public @interface Species {

String value() default "";
}

关于java - 通过 CDI 动态注入(inject)实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33583032/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com