2013-02-25 7 views
11

Nehmen wir an, ich habe eine Auto-Klasse. In meinem Code möchte ich 10 Autos erstellen. Die Klasse "Auto" enthält einige mit @Inject annotierte Abhängigkeiten. Was wäre der beste Ansatz dafür?So erstellen Sie Instanzen im laufenden Betrieb in CDI

CDI hat eine Provider-Schnittstelle, die ich die Autos erstellen können:

@Inject Provider<Car> carProvider; 
public void businessMethod(){ 
    Car car = carProvider.get(); 
} 

Leider das funktioniert nicht, wenn ich die nicht über eine CarFactory haben, die eine Methode mit @Produces Anmerkung hat, die erzeugt Auto. So sehr es die reale Welt widerspiegelt, dass ich keine Autos ohne Fabrik bauen kann, ich möchte lieber keine Fabriken für alles schreiben. Ich möchte nur, dass der CDI-Container mein Auto wie jede andere Bohne erstellt. Wie empfehlen Sie, dass ich diese Autos erstelle?

Antwort

8

Verwenden Sie stattdessen die javax.enterprise.inject.Instance-Schnittstelle.

So:

public class Bean { 

    private Instance<Car> carInstances; 

    @Inject 
    Bean(@Any Instance<Car> carInstances){ 
     this.carInstances = carInstances; 
    } 

    public void use(){ 
     Car newCar = carInstances.get(); 
     // Do stuff with car ... 
    } 

} 
+0

Das ist eigentlich, was ich am Ende benutzt habe.Könnten Sie Ihr Beispiel korrigieren, ist das Konstruktorargument nicht vom selben Typ wie das Klassenattribut: Car vs UIModule. Auch ich denke, die Injektion sollte Annotetade mit @New statt @Any sein. Und ein besseres Beispiel für die use() - Methode wäre eine, die zeigen würde, wie Sie eine Instanz des Autos bekommen würden. Zum Beispiel 'carInstances.get()' – palto

+0

@New ist in CDI 1.1 veraltet, bevorzugt von @Dependent Beans. Siehe CDI 1.1, Abschnitt 3.14. Ich verstehe es nicht wirklich, was ist los mit einem Anbieter, ich. e., 'CDI.current(). select (Car.class) .get()'? –

+0

@MartinAndersson Das ursprüngliche Problem war, dass ich eine Fabrik für die Verwendung eines Anbieters erstellen musste. Das Beispiel, das Sie im Kommentar angegeben haben, ist für mich völlig neu. Vielleicht könnten Sie daraus eine Antwort erstellen? – palto

2

Sie Qualifier mit @Produces Anmerkungen verwenden:

@Qualifier 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER}) 
public @interface MyCars { 
} 

Probe-Produzent-Methode:

@Produces 
@MyCars 
public Car getNewCar(@New Car car){ 
    return car; 
} 

Nutzung:

@Inject 
@MyCars 
private Provider<Car> carProvider; 
+0

'@New ist in CDI 1.1 veraltet, anstelle von @Dependent Beans. Siehe CDI 1.1, Abschnitt 3.14. –

+0

@MartinAndersson ich weiß das, aber als die Zeit der Antwort CDI 1.1 nicht war, so geht die Antwort auf CDI 1.0 (nur um dies hier zu verdeutlichen) – FibreFoX

0

Eine andere Möglichkeit, es zu tun wäre, um Auto einfach keinen CDI-Bereich zu geben, macht es abhängig und Sie erhalten jedes Mal eine neue Instanz, wenn es injiziert wird und t Schlauchinstanzen werden erst zerstört, wenn die enthaltene Instanz zerstört wird.

+0

der Umfang ist nicht etwas, worüber man sich Sorgen machen muss, soweit ich Es ist klar, dass er einen injizierten Produzenten haben wollte und keine spezifische Produzentenklasse implementieren musste. Du hast Recht, dass alle injizierten cdi-Bohnen '@ abhängig' werden, aber es ist nicht was Palto über – FibreFoX

+0

"eine neue Instanz jedes Mal, wenn es injiziert wird" sprechen? Wie kann ein Abhängiger "jedes Mal" injiziert werden? Die Injektion erfolgt nur einmal. Von einem Proxy. Wenn eine @Dependent-Bean oder ein Proxy injiziert wurde, wird jeder Aufruf an diesen Proxy immer an ein und dieselbe Backing-Bean weitergeleitet. –

+0

Es injiziert den Proxy einmal, ja, aber wenn dieser Proxy in eine abhängige Scoped Bean aufgelöst wird, dann wird diese abhängige Scoped Bean neu auf jeder neuen Instanz von Bean erstellt, die die Injektion anfordert. Die injizierte Bohne wird abhängig vom Lebenszyklus anderer. – LightGuard

5

Mein Lieblingsmodell für programmatische Lookup ist CDI.current().select().get() zu verwenden.

Demonstriert here.

Das Servlet eine Abhängigkeit von zwei CDI Bohnen hat, eine Anfrage scoped und die andere Anwendung scoped:

private final RequestScopedBean requestScoped 
      = CDI.current().select(RequestScopedBean.class).get(); 

private final ApplicationScopedBean applicationScoped 
      = CDI.current().select(ApplicationScopedBean.class).get(); 

Die Testklasse, die dieses Servlet verwendet, kann here finden.

Untersuchen Sie den Code und Sie werden feststellen, dass der Code vollständig mit dem entspricht, was Sie mit @Inject MyBean myBean; erhalten würden.

Verwandte Themen