2016-03-30 8 views
1

In CDI, ich bin in der Lage, eine Bean mit einem bestimmten Bereich zu injizieren, der Bereich, mit dem die Bean-Klasse definiert wurde. Aber was, wenn ich die Bean-Klasse ohne irgendeinen Umfang erstelle und dieser Bohne zum Zeitpunkt der Injektion Spielraum gebe. Meine Anforderung besteht darin, im letzteren Fall ein Injektionszeit-Scoping zu ermöglichen. Problem ist, dass die Injektion mit dependent scope anstelle des gewünschten kommentierten Bereichs geschieht, es sei denn, ich verwende einen producer.In CDI, wie man einer Bohne am Punkt der Einspritzung Spielraum gibt?

Beispiel:

CASE 1:

Als ich Umfang einer Bohne in ihrer Klassendeklaration wie folgt erklären:

@ApplicationScoped 
class UserDetails { 
... 
} 

Und injiziert wie folgt aus:

@ViewScoped 
class UserView { 

    @Inject 
    UserDetails userDetails; 
    . 
    . 
} 

Es funktioniert wie erwartet. Die in den Anwendungsbereich der Anwendung injizierte Bean ist in allen anderen Beans in der gesamten Anwendung verfügbar.


CASE 2:

Aber wenn ich gebe keinen Raum in Klassendeklaration:

class UserDetails { 
... 
} 

Und injiziert wie diese (was Umfang an der Injektionsstelle):

@ViewScoped 
class UserView { 

    @Inject @ApplicationScoped 
    UserDetails userDetails; 
    . 
    . 
} 

Dies ist fehlgeschlagen! .. Die injizierte Bohne hatnicht injiziertaber stattdessen dependent scope (View Scope in meinem Fall).

I hatte eine Producer & a Qualifier wo @Produces Verfahren zu schaffen, wird das Bean in gewünschten application scope bereitstellt. Ich denke, dass diese Producer/Qualifier-Erweiterung ein Overhead ist, wenn ich in diesem Fall die Bean-Klasse UserDetails in application scope injizieren muss.

Die Sache ist, UserDetails Klasse ist Teil eines Drittanbieter-Jar. Diese Klasse hat keinen deklarierten Geltungsbereich und ist ein POJO. Ich kann den Quellcode nicht ändern.

Basierend auf der obigen Diskussion, ich habe zwei Fragen:

  1. Warum jemand Bean-Klassen ohne Bereich definiert schaffen würde, wenn sie wissen, dass die Bohnen unter einem bestimmten Bereich injiziert werden sollen? Würde diese Praxis in puncto Design Vorteile bringen?

  2. Da ich keine Kontrolle über den Quellcode der Bean-Klassen habe und sie keinem Bereich zugeordnet sind, ist Producer/Qualifier extension die einzige gute Möglichkeit, solche Beans in den gewünschten Bereich zu injizieren?

Antwort

4

1.Objekt ohne Bereich definiert - @Dependent verwendet

CDI behandelt Objekt ohne Geltungsbereich als @Dependent scope.

Eine Instanz einer abhängigen Bean wird nie zwischen verschiedenen Clients oder verschiedenen Injektionspunkten geteilt. Es ist streng abhängig von einem anderen Objekt. Es wird instanziiert, wenn das Objekt zu erstellt wird und zerstört wird, wenn das Objekt zerstört ist.

Bohnen mit Bereich @ Dependent benötigen kein Proxy-Objekt. Der Client enthält eine direkte Referenz auf seine Instanz.

Frühling IoC dev: CDI @Dependent Anwendungsbereich ist sehr ähnlich Frühling IoC Prototype Umfang.

2. Wenn nicht verwenden @Produces - Just @Inject

CDI wird für jede Injektion (@Dependent scope) neue Instanz der Userdetails erstellen. Keine Daten teilen hier! Sie können den Bereich nicht wie bei der Injektion definieren.

3. Verwenden Sie @Produces dann @Inject

Sie den Umfang der Userdetails steuern Objekt (ApplicationScoped, SessionScoped oder RequestScoped)

public class Producers { 

    @Produces @ApplicationScoped 
    public UserDetails createUserDetails() { 
     // Initialize UserDetails 
    } 

    public void release(@Disposes UserDetails userDetails) { 
     // Release userDetails if you have to 
    } 
} 

4. Eine andere Möglichkeit: Erweitern Userdetails, wenn möglich

@ApplicationScoped // Or @SessionScoped, @RequestScoped 
    public class UserDetailsImpl extends UserDetails { 
     // 
    } 

Wenn Sie möchten ApplicationScoped für UserDetails. Weg 3 oder Weg 4 kann benutzt werden.

+0

Auf eine Randnotiz könnten Sie dies bitte beantworten: Im Falle des Herstellers, weiß der CDI-Container bereits, dass das injizierte Objekt einen bestimmten Geltungsbereichstyp hat? Im Hintergrund unterscheidet sich die Injektion durch den Produzenten von der einfachen Injektion (Fall 1 meiner ursprünglichen Frage). – user2918640

+0

Ja. CDI weiß, welcher Bereich für die Bean verwendet wurde. Der Bereich wird verwendet, wenn der Bereich definiert wird, wenn Sie Produzieren definieren. Sie können den Geltungsbereich der Bean nicht ändern, indem Sie beim Injizieren den Bereich definieren. – Loc

2

Der Bereich wird immer auf der Bean definiert, nicht auf dem Injektionspunkt.

Ein Injektionspunkt kann den Umfang der injizierten Bean nicht ändern.

0

Ich denke, Sie können eine @ApplicationScoped Bohne als @Dependent Bean injizieren, indem Sie die @New Annotation in der Nähe des Injektionspunkts angeben, aber Sie können das Gegenteil nicht tun.