2017-03-01 4 views
1

Ich habe Klassenhierarchie wo ich Feld mit CDI basierend auf Art der Unterklasse injizieren möchte. Diese Situation ist in der folgenden Java-Code beschrieben:CDI: Injection basierend auf Objektklasse

@Stateless 
public class A { 
    @Inject 
    @MyInjection 
    D d; 
    ... 
    public void templateMethod(){...}; 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

@Stateless 
public class B extends A { 
... 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

@Stateless 
public class C extends A { 
... 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

public class F { 

    @Produces 
    @MyInjection 
    D myProducer(InjectionPoint ip){ 
     Class<?> clazz = ip.getMember().getDeclaringClass(); 

     //if clazz is B then inject one type 

     //if clazz is C then inject other type 

     //default inject default type 
    } 
} 

Diese Bohnen entsprechendes ejb.jar Archiv als Teil der EAR verpackt sind und es gibt beans.xml Datei in der richtigen Stelle. Der Code wird unter Verwendung von Java EE 7 auf Wildfly 10 Server ausgeführt.

Mit diesem Code bekomme ich Klasse der Hierarchie Basisklasse (in diesem speziellen Fall Klasse A), die ist, wenn ich darüber logisch denke, weil InjectionPoint Feld ist in der Tat in Klasse A. Der Punkt ist, dass ich eine Unterscheidung basierend auf Unterklassen machen möchte, obwohl ich in der Oberklasse injizieren.

Kann ich dies mit der InjectionPoint-Klasse erreichen? Gibt es einen möglichen Weg dies zu erreichen?

Mehr dazu, was ich mit diesem Stück Code erreichen möchte. Diese Hierarchie implementiert die Template-Methode Design Pattern und alle Klassen sind konkret. Sie können die Klasse A verwenden, die den allgemeinen Algorithmus und bestimmte Schritte implementiert. Sie können jedoch die Schritte in einigen Unterklassen neu definieren. Außerdem muss ein spezifischer Typ D injiziert werden, der sich je nach Unterklasse unterscheiden kann.

Leider gibt es einen starken Wunsch, Bassklasse A nicht neu zu gestalten. Also versuche ich, etwas in der Basisklasse mit CDI zu injizieren und verwende keinen Deployment Deskriptor.

+0

Bitte erwähnen Sie in Ihrer Frage alles, was Sie versuchten –

Antwort

1

Von Ihrer Frage habe ich verstanden, dass Sie bestimmen möchten, was Bean Sie in es injizieren. Dies kann auf folgende Weise erreicht werden:

@Produces 
@MyInjection 
D myProducer(InjectionPoint ip){ 
    // this will give you the class of the bean you injected into 
    ip.getBean().getBeanClass(); 
} 

Zur Vollständigkeit Ihrer bisherigen Lösung ip.getMember() verwendet, die eine Method Objekte zurückgibt (oder Field für Feld Produzenten). Daher wird nachfolgender Anruf an getDeclaringClass() Ihnen class A geben.

+0

Siliarus danke für Ihre Antwort, aber unglücklicherweise ip.getBean() in meinem speziellen Fall gibt null zurück. Fürs Erste ist es ein Rätsel für mich. –

+0

Null zurückgeben? Nun, das bedeutet wahrscheinlich, dass Sie "falsche" Bereiche für Bohnen haben. Weil 'InjectionPoint' nur funktioniert, wenn Sie in' @ Dependent'-Bean injizieren (lesen Sie mehr [hier] (http://docs.jboss.org/cdi/spec/1.2/cdi-spec.html#injection_point)). Was ist der Umfang deiner Bohnen 'A',' B' und 'C'? – Siliarus

+0

Ich glaube, es ist '@ Dependent'. Soweit ich weiß, ist '@ Dependent' der Standardbereich, wenn Bean nicht mit Anmerkungen versehen ist. Liege ich falsch? –

0

Nach ein bisschen Basteln fand ich einen Weg, um das Verhalten in meiner Frage zu erreichen. Dies erforderte einen anderen Ansatz zur CDI-Injektion: anstelle der Feldinjektion hat die Konstruktorinjektion die Aufgabe erfüllt.

public class A { 
    D d; 
    ... 

    public A(){ 
     this.d = null; 
    } 

    @Inject 
    public A(@MyInjection D d){ 
     this.d = d; 
    } 
    ... 
    public void templateMethod(){...}; 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

@Stateless 
public class B extends A { 
    ... 
    public B(){ 
     super(); 
    } 

    @Inject 
    public B(@MyInjection D d){ 
     super(d); 
    } 
    ... 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

@Stateless 
public class C extends A { 
    ... 
    public B(){ 
     super(); 
    } 

    @Inject 
    public B(@MyInjection D d){ 
     super(d); 
    } 
    ... 
    protected void step1(){...}; 
    protected void step2(){...}; 
} 

public class F { 

    @Produces 
    @MyInjection 
    D myProducer(InjectionPoint ip){ 
     Class<?> clazz = ip.getMember().getDeclaringClass(); 

     //if clazz is B then inject one type 

     //if clazz is C then inject other type 

     //default inject default type 
    } 
} 

auf diese Weise organisiert Code ich in der Lage bin Injektion zu unterscheiden, basierend auf Blatt Klassen, obwohl die Anforderung von nicht-Code der Basisklasse zu ändern (Teil einer API) möglicherweise nicht möglich sein, zu erreichen.