使用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;
您可以制作制作动物的生产者方法,例如,使用限定符制作特定动物:
@Produces @AnimalType
public Animal makeAnimal(InjectionPoint ip) {
// Get AnimalType qualifier and make a new Animal(typeString),
// ...
return animal;
}
但如何生成所有(从数据中知道的)动物,以便使用实例对它们进行迭代?
for(Animal animal : animals) {
// ...
}
我确实希望每只动物都能从依赖注射和其他Weld/CDI产品中获益。
就我所理解的InjectionPoint概念而言,您不能以这种方式将其用于实例。实例和InjectionPoint with producer方法用于注入
Instance<Animal>
将所有CDI动物纳入生产者方法,并让生产者方法根据注射点决定返回哪种动物:
public Animal make(@Any Instance<Animal> instance, InjectionPoint ip)
也看这里https://www.javacodegeeks.com/2013/06/java-ee-cdi-programmatic-dependency-disambiguation-example-injection-point-inspection.html
或者生成一个已配置的对象,具体取决于下面的限定符配置输入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方法。恐怕这不合适。
要使用注入点,可以使AnimalType不是限定符
@Retention(RUNTIME)
@Target({TYPE, METHOD, FIELD, PARAMETER})
public @interface AnimalType {
String value();
}
现在必须使用注入点:
@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");
}
但您不能将实例注入到bean中,因为缺少限定符AnimalType。因此,您必须生成一个简单的列表,如下所示:
@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;
看来你要找的是无人管理
Unmanaged<Animal> unmanagedAnimal = new Unmanaged<>(Animal.class);
UnmanagedInstance<Animal> animalInstance = unmanagedAnimal.newInstance();
Animal animal = animalInstance.produce().inject().postConstruct().get();
它基本上是一个依赖作用域bean,但完成后需要手动销毁它。
我的JavaEE应用程序中有一个单例类。我通过使用注释类并让CDI处理所有事情来实现这一点。 我的问题是,我是否可以防止这个类的意外手动实例化,因为CDI要求我有一个非私有的无参数构造函数? “经典”非CDI解决方案将有一个私有构造函数、一个静态字段和一个返回此实例的静态工厂方法。
在我看来,下面的结果应该是两个字段指向同一个实例, 但这似乎不是真的,因为第一次和第二次我得到了 Bean的引用是否应该在给定的上下文中重用?我错过了什么?
我有一个用@ApplicationScoped注释的CDIBean。有没有一种方法可以告诉Spring在组件扫描期间拾取它,就像它被@component注释一样?Spring确实理解@Inject注释,那么为什么不@ApplicationScoped呢? 这个想法是,在Spring中使用CDI bean会很方便(至少如果他们只使用普通的依赖注入,而没有像拦截器、装饰器这样花哨的CDI东西...)
我在JBoss EAP 6上使用Java EE 6,我的JSF bean注释如下:(都来自包) 但是,它们也是CDI bean(默认构造函数,使用、等)。我一直读到不能混合这些注释(JSF和CDI),但它显然工作得很好:注入工作正常,视图更改时调用preDestroy等)。 我是不是漏掉了什么?问题出在哪里?为什么不用呢?
我有一个JAR文件,其中包含一个请求范围Bean。(一个注释为的类)。 我有另一个Web服务项目(作为WAR文件构建)。上述JAR文件位于WAR文件的文件夹中。 我试图的类到Web服务项目中的一个类中。 我正在得到一个 这两个项目都有JAR文件,WAR文件包含一个空的。我已经研究这个问题好几天了。请帮忙。 谢谢
我有一个JSF的问题,CDI项目。我做了大量研究,发现在CDI中没有注释。我用对话框解决基于ajax的页面的问题。我想将变量从DataTable传递到dialog。为此,我不能使用bean,因为在请求结束后会丢弃值。有人能帮我解决吗?我不能使用,但这是一个糟糕的做法。或者只保存这一个变量到会话谁知道。你们能给我一些提示如何优雅地解决这个问题吗? 以下是错误消息: