使用Wildfly / JBoss Weld / CDI 1.1。
假设你有一个数据库。可以是任何东西,MySQL,MongoDB。可以是REST服务。从该数据库中,您可以获得动物列表。
[
"Cat",
"Dog",
"Giraffe",
"Tiger",
"Chicken"
]
您不知道您将从此服务中获得哪些动物,但您想要做的是将它们用于实例注射。
动物类:
public class Animal {
private final String type;
public String getType() {
return type;
}
public Animal(String aType) {
type = aType;
}
}
注射点:
@Inject @Any
public Instance<Animal> animals;
你可以制作一个制作AN动物的制作人方法,例如用限定词来制作某种动物:
@Produces @AnimalType
public Animal makeAnimal(InjectionPoint ip) {
// Get AnimalType qualifier and make a new Animal(typeString),
// ...
return animal;
}
但是,如何生成ALL(从数据中获知)动物,以便您可以使用实例迭代它们?
for(Animal animal : animals) {
// ...
}
我确实希望每个Animal都能获得依赖注入和其他Weld / CDI好处的好处。
答案 0 :(得分:1)
您好像在寻找Unmanaged
Unmanaged<Animal> unmanagedAnimal = new Unmanaged<>(Animal.class);
UnmanagedInstance<Animal> animalInstance = unmanagedAnimal.newInstance();
Animal animal = animalInstance.produce().inject().postConstruct().get();
它基本上是一个依赖的scoped bean,但你需要在完成时手动销毁它。
答案 1 :(得分:0)
据我了解InjectionPoint概念,您不能以这种方式将它与Instance一起使用。带有producer-method的Instance和InjectionPoint用于注入
Instance<Animal>
进入带有所有CDI动物的生产者方法,让生产者方法决定,返回哪种动物,取决于注射点:
public Animal make(@Any Instance<Animal> instance, InjectionPoint ip)
或者生成一个已配置的对象,具体取决于Qualifier-Config-Inputs,例如https://dzone.com/articles/cdi-di-p2
在你的情况下,你必须告诉CDI,如何找到生产者方法:
@Qualifier
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface AnimalType {
String value();
}
然后你可以编写适当的生成器方法:
@Produces
@AnimalType("Monkey")
public Animal makeAnimalApe() {
return new Animal("Cheetah");
}
@Produces
@AnimalType("Mouse")
public Animal makeAnimalMouse() {
return new Animal("Jerry");
}
@Produces
@AnimalType("Cat")
public Animal makeAnimalCat() {
return new Animal("Tom");
}
然后你可以注射它:
@Inject
@Any
private Instance<Animal> anyAnimal;
@Inject
@AnimalType("Monkey")
private Animal monkey;
@PostConstruct
public void create(){
System.out.println(monkey.name);
anyAnimal.forEach((a)->System.out.println(a.name));
}
但在这种情况下,你必须为每个选择案例编写一个producer-method。我担心,那不合适。
要使用InjectionPoint,您可以使AnimalType不是限定符
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface AnimalType {
String value();
}
现在你必须使用InjectionPoint:
@Produces
public Animal makeAnimalApe(InjectionPoint p) {
AnimalType t = p.getAnnotated().getAnnotation(AnimalType.class);
if (t != null) {
String s = t.value();
if ("Monkey".equals(s))
return new Animal("Cheetah");
else if ("Mouse".equals(s))
return new Animal("Jerry");
else if ("Cat".equals(s))
return new Animal("Tom");
}
throw new EJBException("Please annotate the animal injection point with AnimalType");
}
但是你不能将Instance注入你的bean,因为缺少Qualifier AnimalType。所以你必须像这样产生一个简单的List:
@Produces
public List<Animal> produceAll(){
List<Animal> all = new ArrayList<>();
all.add(new Animal("Cheetah"));
all.add(new Animal("Jerry"));
all.add(new Animal("Tom"));
return all;
}
所以你可以只注射一个或所有
@Inject
@AnimalType("Monkey")
private Animal monkey;
@Inject
private List<Animal> all;