2016-04-13 11 views
2

Arbeiten mit Wildfly/JBoss Weld/CDI 1.1.CDI Dynamische Bean Instanzen

Nehmen wir an, Sie haben eine Datenbank. Kann alles sein, MySQL, MongoDB. Könnte ein REST-Dienst sein. Aus dieser Datenbank erhalten Sie eine Liste der Tiere.

[ 
    "Cat", 
    "Dog", 
    "Giraffe", 
    "Tiger", 
    "Chicken" 
] 

Sie wissen nicht, was Tiere, die Sie von diesem Service bekommen, aber was Sie wollen, ist zu tun, damit sie zum Beispiel Injektion zur Verfügung.

Tier Klasse:

public class Animal { 
    private final String type; 
    public String getType() { 
    return type; 
    } 
    public Animal(String aType) { 
    type = aType; 
    } 
} 

Injection Point:

@Inject @Any 
public Instance<Animal> animals; 

Sie können eine Producer-Methode machen, die mit einem Qualifier ein Tier, zum Beispiel macht ein bestimmtes Tier zu machen:

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

Aber wie produzieren Sie ALLE (von Daten bekannten) Tiere, so dass Sie mit Instanzen über sie iterieren können?

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

ich jedes Tier will die Vorteile von Dependency Injection und anderem Weld/CDI Leckereien zu bekommen.

Antwort

1

Es scheint, wie Sie für Unmanaged

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

Sein im Allgemeinen eine abhängige scoped Bohne suchen konnten, aber Sie müssen es manuell zerstören, wenn Sie fertig.

+0

Unmanaged es verwendet, um nicht-Bean-Klasse in einer Injektionsziel zu verwandeln. Hier besteht die Notwendigkeit, Tiere überall injizieren zu können. Unmanaged ist nicht genug dafür. Die einzige Lösung ist, diese Tiere Bohnen zu machen ... –

0

Soweit ich das InjectionPoint-Konzept verstehe, können Sie es nicht mit Instance auf diese Weise verwenden. Instanz und InjectionPoint mit dem Produzenten-Methode verwendet, um die

Instance<Animal> 

in den Hersteller-Verfahren mit allen CDI-Tiere und lassen Sie den Hersteller-Verfahren entscheiden, zu injizieren, welches Tier zurückzukehren, auf der InjectionPoint abhängig:

public Animal make(@Any Instance<Animal> instance, InjectionPoint ip) 

Siehe auch hier https://www.javacodegeeks.com/2013/06/java-ee-cdi-programmatic-dependency-disambiguation-example-injection-point-inspection.html

Oder ein konfiguriertes Objekt, abhängig von Qualifier-Config-Eingängen wie hier https://dzone.com/articles/cdi-di-p2

zu produzieren

In Ihrem Fall müssen Sie CDI sagen, wie die Hersteller-Methoden finden:

@Qualifier 
    @Retention(RUNTIME) 
    @Target({TYPE, METHOD, FIELD, PARAMETER}) 
    public @interface AnimalType { 
     String value(); 
    } 

Dann können Sie die entsprechenden Produzenten Methoden schreiben:

@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"); 
} 

Und dann kann man es injizieren:

@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)); 
} 

Aber in diesem Fall müssen Sie für jeden Selektionsfall eine Producer-Methode schreiben. Ich fürchte, das ist nicht geeignet.

Um die InjectionPoint verwenden, können Sie die AnimalType KEINE Qualifier machen

@Retention(RUNTIME) 
@Target({TYPE, METHOD, FIELD, PARAMETER}) 
public @interface AnimalType { 
    String value(); 
} 

Jetzt müssen Sie die InjectionPoint verwenden:

@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"); 
} 

Aber man kann nicht Instanz in Ihrem Bean injizieren, weil Mangel an der Qualifier AnimalType. Also müssen Sie eine einfache Liste wie folgt erzeugen:

@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; 
} 

So können Sie injizieren nur eine oder alle

@Inject 
@AnimalType("Monkey") 
private Animal monkey; 
@Inject 
private List<Animal> all; 
Verwandte Themen