当前位置: 首页 > 知识库问答 >
问题:

CDI动态Bean实例

国高杰
2023-03-14

使用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产品中获益。

共有2个答案

宋鸿
2023-03-14

就我所理解的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;
樊宏义
2023-03-14

看来你要找的是无人管理

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,因为在请求结束后会丢弃值。有人能帮我解决吗?我不能使用,但这是一个糟糕的做法。或者只保存这一个变量到会话谁知道。你们能给我一些提示如何优雅地解决这个问题吗? 以下是错误消息: