【问题标题】:CDI Dynamic Bean InstancesCDI 动态 Bean 实例
【发布时间】:2016-08-05 06:18:17
【问题描述】:

使用 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;

您可以创建一个制作动物的 Producer 方法,例如使用限定符来制作某种动物:

@Produces @AnimalType
public Animal makeAnimal(InjectionPoint ip) {
  // Get AnimalType qualifier and make a new Animal(typeString), 
  // ...
  return animal;
}

但是您如何生成所有(从数据中得知)动物,以便您可以通过实例对它们进行迭代?

for(Animal animal : animals) {
  // ...
}

我确实希望每只动物都能从依赖注入和其他 Weld/CDI 好东西中受益。

【问题讨论】:

    标签: java cdi wildfly java-ee-7 weld


    【解决方案1】:

    您可能正在寻找Unmanaged

    Unmanaged<Animal> unmanagedAnimal = new Unmanaged<>(Animal.class);
    UnmanagedInstance<Animal> animalInstance = unmanagedAnimal.newInstance();
    Animal animal = animalInstance.produce().inject().postConstruct().get();
    

    它基本上是一个依赖作用域的bean,但你需要在完成后手动销毁它。

    【讨论】:

    • 非托管它用于转换注入目标中的非 bean 类。这里需要能够在任何地方注射动物。非托管是不够的。唯一的解决办法就是把这些动物做成豆子……
    【解决方案2】:

    据我了解 InjectionPoint 概念,您不能以这种方式将其与 Instance 一起使用。 Instance 和 InjectionPoint 与 producer-method 用于注入

     Instance<Animal>
    

    与所有 CDI 动物一起进入生产者方法,然后让生产者方法决定返回哪个动物,具体取决于 InjectionPoint:

     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

    或者根据 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));
    }
    

    但是在这种情况下,您必须为每个选择情况编写一个生产者方法。恐怕,那不合适。

    要使用 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");
    }
    

    但是由于缺少限定符 AnimalType,您不能将 Instance 注入到您的 bean 中。所以你必须像这样生成一个简单的列表:

    @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-10
      • 2013-03-05
      • 1970-01-01
      • 2016-02-08
      • 2013-11-26
      • 2014-03-15
      • 2017-05-02
      • 1970-01-01
      • 2013-02-10
      相关资源
      最近更新 更多