Wie zu verwenden CDI-Qualifikation mit mehreren Klassen-Implementierungen?
Ich bin neu in der Java EE/JSF und nun Lesen Sie über die CDI-Qualifier - die Möglichkeit zum wechseln der Klasse Umsetzung. Das ist großartig, aber ich habe eine Frage. Soweit ich das verstehe kann ich ändern, Klasse Umsetzung unter Nutzung der qualifier, aber ich brauche, um es zu ändern wo ich den Einsatz dieser Implementierung. Was ist die beste Lösung, um es in einem Ort? Mit meinem kleinen wissen über Java EE dachte ich dieses.
Können sich vorstellen, dass wir die Erstellung von einfachen Rechner-Anwendung. Wir brauchen paar Klassen:
Calculator
(basic-Implementierung des Rechners)ScientificCalculator
(wissenschaftliche Umsetzung der Rechner)MiniCalculator
(mit mindestens Potentialität)MockCalculator
(für unit-tests)- Qualifier
@Calculator
(anzeigen wird die tatsächliche Umsetzung der Rechner; sollte ich die Qualifikation für jede Implementierung?)
Ist hier die Frage. Ich habe vier Implementierungen der Rechner und ich will einer von Ihnen in wenigen Orten, aber nur eine zur Zeit (in der ersten Projekt-phase I verwenden MiniCalculator
, dann Calculator
und so weiter). Wie kann ich eine änderung der Implementierung ohne änderung des Codes in jedem Ort, wo ein Objekt injiziert wird? Sollte ich die Fabrik, die verantwortlich für die Injektion und wird als method injector
? Ist meine Lösung korrekt und aussagekräftig?
Fabrik
@ApplicationScoped
public class CalculatorFctory implements Serializable {
private Calculator calc;
@Produces @Calculator Calculator getCalculator() {
return new Calculator();
}
}
Klasse, die verwendet Calculator
public class CalculateUserAge {
@Calculator
@Inject
private Calculator calc;
}
Ist dies die richtige Lösung? Bitte korrigieren Sie mich, wenn ich falsch bin oder ob es eine bessere Lösung. Vielen Dank!.
InformationsquelleAutor pepuch | 2013-03-16
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie möchten, tauschen Sie die Umsetzung in Ihrem code über eine factory-Methode, dann die factory-Methode ist die Verwaltung, die Bohnen und nicht die CDI und so gibt es wirklich keine Notwendigkeit für
@Calculator
.Jedoch wenn Sie möchten, dass Ihre Caclulator Bohnen werden von CDI verwalteten für Injektionen und life-cycle-management mit @PostConstruct etc, dann Sie können verwenden Sie eine der folgenden Vorgehensweisen.
Ansatz 1 :
Vorteil :Sie können, vermeiden Sie die annotation mit
@Named("miniCalculator")
Nachteil : der compiler wird keinen Fehler mit diesem Ansatz, wenn es eine Namensänderung von sagen
miniCalculator
zuxyzCalculator
.Ansatz 2 : Empfohlene (Compiler verfolgt, Einspritzung, wenn jede Injektion fehl)
Ansatz 3: Wenn Sie über eine factory-Methode generieren, die Ihr Objekt.Seine lifecycle-nicht verwaltet werden, die CDI, aber die Injektion wird gut funktionieren mit @Inject .
Allen drei Ansätzen wird die Arbeit für die Prüfung , sagen wir, Sie haben eine Klasse namens CaculatorTest,
wenn Sie möchten, verwenden Sie eine mock-Implementierung in Ihrem test dann so etwas tun,
Es gibt keinen Grund zu kommentieren, nichts mit
@Produces
wenn Sie dabei sind, nennen Sie es selbst.Wie würden Sie injizieren dieser service zu einer CDI bean ? Wir würden uns über
@Produces @myservice @WebServiceRef(lookup="java:app/service/PaymentService") {} @Inject @myservice MyWebService;
In diesem Fall container, nicht gelingt, MyWebServiceImpl Lebenszyklus , es ist lediglich Injektion@Produces
Bohnen sind noch geschafft von CDI, es sei denn, es instanziiert wird innerhalb der Methode alsnew()
. Ich habe korrigiert meine definition der Verwendung von Ansatz 3.InformationsquelleAutor Avinash Singh
Gibt es mehrere Themen hier.
@ - Alternativen
.@PostConstruct
. Außerdem kann es zur Prüfung der einspritzzeitpunkt-und runtime Entscheidungen darüber, was zu injizieren. Siehe link 2. für einige Hinweise.Ist diese Lösung korrekt? Das wird funktionieren, aber Sie werden immer noch Durcheinander mit dem code zum ändern der Umsetzung, so betrachten 1. erste. Auch
@Calculator Calculator
scheint mir sehr überflüssig. Wieder, finden Sie unter dem link im 2.Update:
CDI verwendet Qualifier zusätzlich Typen für die Auflösung von Abhängigkeiten. In anderen Worten, so lange als es nur einen Typ entspricht dem Typ des injection-point, Arten allein sind genug, und Qualifier) werden nicht benötigt. Qualifier gibt es für die disambiguierung, wenn die Typen alleine sind nicht genug.
Beispiel:
In der Lage sein, um zu injizieren, die entweder die Umsetzung, Sie müssen nicht jedem Qualifier:
oder
Deswegen sage ich
@Calculator Calculator
redundant ist. Wenn Sie definieren einen qualifier für jede Implementierung, Sie sind nicht zu gewinnen viel, könnte genauso gut mit dem Typ. Sagen wir, zwei Qualifikanten@QualOne
und@QualTwo
:und
Beispiel direkt oberhalb der nicht zu gewinnen ist da nichts in dem vorherigen Beispiel keine dis-Mehrdeutigkeit existiert bereits.
Sicher, Sie können dies tun, für Fälle, in denen Sie keinen Zugriff haben, um insbesondere die Umsetzung-Typen:
und
@Avinash Singh - CDI verwaltet@Produces
sowie alles, was Sie zurückgeben, solange es ist die CDI, der die Methode aufruft. Sehen dieser Abschnitt der spec wenn Sie bitte. Dies schließt Rückkehr `@...Scoped beans, die Unterstützung von dependency injection -, Lebenszyklus-callbacks, etc.Übersah ich einige details hier, so betrachten wir die folgenden zwei:
und
Dann, im ersten Beispiel, CDI verwaltet den Lebenszyklus (d.h.
@PostConstruct
und@Inject
Unterstützung), was zurückgegeben wird, vom Hersteller, aber in der zweiten wird es nicht.Zurück auf die ursprüngliche Frage - was ist der beste Weg zum wechseln zwischen Implementierungen ohne änderung der Quelle? Die Annahme ist, dass Sie wollen das ändern, werden Breite Anwendung.
Dann, jeder für jeden
@Inject MyInterface instance
,ImplOne
wird injiziert werden, es sei denn,ist angegeben, in welchem Falle
ImplTwo
wird injiziert werden, überall.Weiteres Update
Gibt es tatsächlich Dinge, in die Java-EE-Umgebung, die nicht in der Trägerschaft CDI, wie EJBs und web services.
Wie würden Sie injizieren eines web service in eine CDI managed bean? Es ist wirklich einfach:
Ist es, dort müssen Sie einen gültigen Verweis auf die payment-service verwalteten außerhalb CDI.
Aber was ist, wenn Sie nicht wollen, um die volle
@WebServiceRef(lookup="java:app/service/PaymentService")
überall Sie es brauchen? Was ist, wenn Sie nur wollen, um es zu injizieren, indem Sie Typ? Dann müssen Sie dieses irgendwo:und in jede CDI-bean, die einen Verweis auf das payment-service können Sie einfach
@Inject
es mit CDI wie diese:Beachten Sie, dass vor der Festlegung der Produzenten-Feld
PaymentService
wäre nicht verfügbar für die Injektion werden die CDI Weg. Aber es ist immer verfügbar, die alten Weg. Auch in jedem Fall der web service ist nicht gelungen, durch die CDI aber die Festlegung der Produzenten-Feld einfach macht, die web-service-Referenz für die Injektion der CDI Weg.Qualifier
.Also
@Produces @WebServiceRef(lookup="java:app/service/PaymentService") MyWebServiceImpl get()
entspricht@Produces MyWebServiceImpl get()
soweit CDI betroffen ist.Wie würden Sie injizieren dieser service zu einer CDI bean ? Wir würden uns über
@Produces @myservice @WebServiceRef(lookup="java:app/service/PaymentService") {} @Inject @myservice MyWebService;
In diesem Fall container, nicht gelingt, MyWebServiceImpl Lebenszyklus , es ist lediglich InjektionFinden Sie in meinem nächsten update.
Danke für deine Antwort. Es ist eine weitere Szenario , sagen wir, wir haben zwei PamentService von Webservice-und wir wollen
@Produces @service1 @WebServiceRef(lookup="java:app/service/PaymentService1") PaymentService paymentService;
dann würden wir brauchen einen qualifier@service1
in Variablen declaraion sonst würde es werfen Fehler, da es nicht in der Lage, zu beheben, der die korrekte Umsetzung. Entweder Weg, den Lebenszyklus der web-service-oder bean nicht geschafft bis wir erklären, die Bohne selbst mit Anmerkung@Named
InformationsquelleAutor rdcrng