CDI Mehrdeutige Abhängigkeit mit @Products - warum?

9

Ich verwende den folgenden Code:

%Vor%

Wenn ich eine Anwendung auf Glassfish (Java EE 6 btw) veröffentliche, bekomme ich

AmbiguousResolutionException: WELD-001318 Cannot resolve an ambiguous dependency between (...) Car with qualifiers [@Any @Default] (...) Producer Method [Car] with qualifiers [@Any @Default]

Ich weiß, wenn ich @Alternative zur Car-Klasse hinzufüge, wird es funktionieren, aber ich frage mich, ob dies der richtige Weg ist, und warum muss ich es tun?

Können Sie mir sagen, wie @Produces in diesem Fall richtig verwendet wird?

Ich benutze Java EE 6, CDI 1.0, EJB 3.1, Glassfish 3.2

    
dmydlarz 10.04.2014, 08:16
quelle

3 Antworten

12

Der Fehler kommt von der Tatsache, dass Sie zwei Beans vom Typ Car haben, wobei einer die Klasse ist und der andere der Produzent. Sie haben zwei offensichtliche Lösungen, um die Mehrdeutigkeit zu beheben:

Zuerst setzen Sie die Logik hinter isBatmanCar field in der ursprünglichen Klasse (z. B. in einem Konstruktor oder einer @PostConstruct -Methode) und entfernen Ihren Producer. Das würde nur eine Car Bean übriglassen.

Oder wenn Sie wirklich 2 Bean haben wollen oder es nicht vermeiden können, sollten Sie einen Qualifier für Ihre produzierte Bean erstellen:

%Vor%

und benutze es auf Produzenten,

%Vor%

um die Art des Autos injizieren zu können

%Vor%

Qualifier ist die natürliche Option, um mehrdeutige Injektionen aufzulösen. Die Verwendung von @Alternative funktioniert auch, aber es ist hier mehr ein Trick als eine gute Übung.

Letzte Bemerkung: @New ist hier nicht notwendig, da Ihre Car Bean keinen Geltungsbereich hat (also @Dependent scoped). @New ist nur nützlich, wenn ein Producer eine Bean mit einem Bereich injiziert, der nicht @Dependent ist. Das heißt, dieser Code ist nicht sehr nützlich, wenn Ihre Car -Klasse im Bereich @Dependent ist.

    
Antoine Sabot-Durand 10.04.2014, 10:12
quelle
8

Die Verwendung von @Alternative funktioniert, sollte aber nur verwendet werden, wenn Sie es über beans.xml aktivieren möchten.

Das Unterdrücken des Standardkonstruktors Ihrer Bean funktioniert auch, aber Sie können Ihre Bean nicht in einem anderen Bereich als @RequestScoped verwenden.

Die Verwendung Ihres eigenen Qualifizierers funktioniert, ist aber nicht sehr nützlich, wenn Sie nur eine Implementierung haben und Ihre Bean nur mit einem Produzenten und nicht mit seinem Konstruktor instanziieren wollen.

Der einfachste Weg ist, Ihre Bean @ Anny mit Anmerkungen zu versehen:

%Vor%

Dinge, die Sie beachten sollten:

  • Alle Beans und Produzenten sind immer implizit für @Any
  • qualifiziert
  • Bohnen und Erzeuger ohne ausdrückliche Qualifikationsmerkmale sind implizit als @Default
  • qualifiziert
  • Bohnen und Erzeuger mit expliziten Qualifiern sind nicht länger implizit als @Default
  • qualifiziert
  • Injektionspunkte ohne explizite Qualifizierer sind implizit @Default, aber nicht @Any
  • qualifiziert

Bei all dem sieht derselbe Code wie oben explizit so aus:

%Vor%

Es wird offensichtlich, dass der Standardkonstruktor der Bean keine gültige Möglichkeit für den Injektionspunkt ist und der Hersteller eine gültige Möglichkeit darstellt.

    
Nicolas Lepage 17.03.2016 09:52
quelle
5

Eine andere Möglichkeit wäre, einen nicht standardmäßigen Konstruktor in der Klasse Car zu erstellen:

%Vor%

Durch Entfernen des Standardkonstruktors kann die Car-Klasse nicht mehr zum Erstellen von Instanzen verwendet werden, die durch Injektion verwendet werden.

Und ändern Sie Ihre Producer-Methode zu

%Vor%

Dann wäre die Producer-Methode die einzige Möglichkeit, Ihre Autos zu erstellen.

Diese Methode kann verwendet werden, wenn Sie wissen, dass Sie immer eine benutzerdefinierte Instanz benötigen und keinen Standardkonstruktor benötigen. Aber normalerweise ist Antoine Lösung nützlicher.

    
Gas 06.09.2014 14:55
quelle

Tags und Links