it-swarm.com.de

Java EE 6 @ javax.annotation.ManagedBean vs. @ javax.inject.Named vs. @ javax.faces.ManagedBean

Ich habe das Gefühl, dass die Java EE 6-Spezifikation ein bisschen durcheinander ist. Es gibt mehrere Sätze von Anmerkungen.

Wir haben javax.ejb Anmerkungen wie @Stateful und @Stateless zum Erstellen von EJBs.

Da ist auch ein @javax.annotation.ManagedBean, um eine verwaltete Bean zu erstellen.

Es gibt Anmerkungen in javax.enterprise.context mögen @SessionScoped und @RequestScoped.

Was mehr ist, gibt es auch @ManagedBean und @SessionScoped/@RequestScoped Anmerkungen in javax.faces.bean Paket.

Und um die Sache noch komplizierter zu machen, gibt es ein Paket javax.inject mit @Named Anmerkung.

Kann jemand bitte beschreiben, in welcher Beziehung sie zueinander stehen?

Wo kann ich @EJB, @Inject oder @ManagedPropery andere Bohnen spritzen?

105
Piotr Gwiazda

Lassen Sie mich zunächst einige Klarstellungen vornehmen:

Managed Bean-Definition : Im Allgemeinen ist ein Managed Bean ein Objekt, dessen Lebenszyklus (Aufbau, Zerstörung usw.) von einem Container verwaltet wird.

In Java ee haben wir viele Container, die den Lebenszyklus ihrer Objekte verwalten, wie JSF-Container, EJB-Container, CDI-Container, Servlet-Container usw.

Alle diese Container arbeiten unabhängig voneinander. Sie werden bei der Initialisierung des Anwendungsservers gestartet und durchsuchen Klassen aller Artefakte, einschließlich JAR-, EJB-JAR-, WAR- und EAR-Dateien, während der Bereitstellungszeit und erfassen und speichern einige Metadaten zu diesen, wenn Sie ein Objekt benötigen Während der Laufzeit einer Klasse geben sie Ihnen Instanzen dieser Klassen und zerstören sie nach Beendigung des Jobs.

Wir können also sagen, dass wir:

  • JSF verwaltete Bohnen
  • CDI verwaltete Bohnen
  • EJB verwaltete Bohnen
  • Und selbst Servlets sind verwaltete Beans, da sie von einem Container, einem Servlet-Container, instanziiert und zerstört werden.

Wenn Sie das verwaltete Bean-Wort sehen, sollten Sie nach dem Kontext oder Typ fragen (JSF, CDI, EJB usw.).

Dann könnten Sie sich fragen, warum wir viele dieser Container haben: AFAIK, Java EE-Leute wollten ein Abhängigkeitsinjektionsframework, aber sie konnten nicht alle Anforderungen in einer Spezifikation zusammenfassen, weil sie das nicht vorhersagen konnten zukünftige Anforderungen und sie machten EJB 1.0 und dann 2.0 und dann 3.0 und jetzt 3.1, aber das Ziel von EJB war nur für einige Anforderungen (Transaktion, verteiltes Komponentenmodell usw.).

Gleichzeitig (parallel) wurde ihnen klar, dass sie auch JSF unterstützen müssen, dann machten sie JSF Managed Beans und einen weiteren Container für JSF-Beans und betrachteten es als einen ausgereiften DI-Container, aber es war immer noch kein vollständiger und ausgereifter Container.

Danach haben Gavin King und einige andere nette Leute CDI gemacht, was der ausgereifteste DI-Container ist, den ich je gesehen habe. CDI (inspiriert von Seam2, Guice und Spring) wurde entwickelt, um die Lücke zwischen JSF und EJB und vielen anderen nützlichen Dingen wie Pojo-Injektion, Herstellermethoden, Interzeptoren, Dekoratoren, Integrations-SPI, sehr flexibel usw. zu füllen, und es kann sogar Was die von EJB und JSF verwalteten Beans tun, dann können wir nur einen ausgereiften und leistungsstarken DI-Container haben. Aber aus Gründen der Abwärtskompatibilität und aus politischen Gründen Java EE-Leute wollen sie behalten !!!

Hier finden Sie die Unterschiede und Anwendungsfälle für jeden dieser Typen:

JSF Managed Beans, CDI Beans und EJBs

JSF wurde ursprünglich mit einem eigenen Mechanismus für das Injizieren verwalteter Beans und Abhängigkeiten entwickelt, der für JSF 2.0 um annotationsbasierte Beans erweitert wurde. Als CDI mit Java EE 6 veröffentlicht wurde, wurde es als Managed-Bean-Framework für diese Plattform angesehen, und natürlich haben die EJBs sie alle überholt, da es sie schon seit weit über einem Jahrzehnt gibt.

Das Problem ist natürlich, zu wissen, welche man verwenden soll und wann man sie verwendet.

Beginnen wir mit den einfachsten, von JSF verwalteten Beans.

JSF Managed Beans

Kurz gesagt, verwenden Sie sie nicht, wenn Sie für Java EE 6 entwickeln und CDI verwenden. Sie bieten einen einfachen Mechanismus für das Einfügen von Abhängigkeiten und das Definieren von Backing-Beans für Webseiten, sind aber weitaus weniger leistungsfähiger als CDI-Bohnen.

Sie können mit der Annotation @javax.faces.bean.ManagedBean definiert werden, für die ein optionaler Namensparameter verwendet wird. Dieser Name kann verwendet werden, um auf die Bean von JSF-Seiten zu verweisen.

Der Bereich kann auf die Bean angewendet werden, indem einer der verschiedenen Bereiche verwendet wird, die im Paket javax.faces.bean definiert sind und die Bereiche request, session, application, view und custom enthalten.

@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
    ....
    ....
}

JSF-Bohnen können ohne irgendeine manuelle Codierung nicht mit anderen Bohnensorten gemischt werden.

CDI-Bohnen

CDI ist das Bean-Management- und Dependency-Injection-Framework, das als Teil von Java EE 6 veröffentlicht wurde und eine vollständige, umfassende Managed-Bean-Funktion enthält. CDI-Beans sind weitaus fortschrittlicher und flexibler als einfaches JSF-Managed Sie können Abfangjäger, Konversationsbereiche, Ereignisse, typensichere Injektionen, Dekoratoren, Stereotype und Erzeugermethoden verwenden.

Um CDI-Beans bereitzustellen, müssen Sie eine Datei namens beans.xml in einem META-INF-Ordner im Klassenpfad ablegen. Sobald Sie dies tun, wird jede Bean im Paket zu einer CDI-Bean. Es gibt viele Funktionen in CDI, von denen es zu viele gibt, um sie hier zu behandeln. Als Kurzreferenz für JSF-ähnliche Funktionen können Sie den Umfang der CDI-Bean mithilfe eines der Bereiche definieren, die in javax.enterprise.context definiert sind. Paket (nämlich Geltungsbereich von Anfragen, Gesprächen, Sitzungen und Anwendungen). Wenn Sie die CDI-Bean von einer JSF-Seite aus verwenden möchten, können Sie ihr einen Namen mit der Annotation javax.inject.Named geben. Um eine Bean in eine andere Bean zu injizieren, kommentieren Sie das Feld mit der Annotation javax.inject.Inject.

@Named("someBean")
@RequestScoped
public class SomeBean {

    @Inject
    private SomeService someService;
}

Eine automatische Injektion wie die oben definierte kann durch die Verwendung von Qualifikationsmerkmalen gesteuert werden, die dabei helfen können, die spezifische Klasse zu bestimmen, die Sie injizieren möchten. Wenn Sie mehrere Zahlungsarten haben, können Sie ein Qualifikationsmerkmal hinzufügen, ob es asynchron ist oder nicht. Während Sie die Annotation @Named als Qualifikationsmerkmal verwenden können, sollten Sie dies nicht tun, da dies zum Anzeigen der Beans in EL vorgesehen ist.

CDI verwaltet die Injektion von Bohnen mit nicht übereinstimmenden Bereichen mithilfe von Proxys. Aus diesem Grund können Sie eine Bean mit Anforderungsbereich in eine Bean mit Sitzungsbereich einfügen, und die Referenz ist für jede Anforderung weiterhin gültig, da der Proxy für jede Anforderung erneut eine Verbindung zu einer Live-Instanz der Bean mit Anforderungsbereich herstellt.

CDI unterstützt auch Interceptors, Ereignisse, den neuen Konversationsumfang und viele andere Funktionen, wodurch es eine viel bessere Wahl gegenüber JSF-verwalteten Beans darstellt.

[~ # ~] ejb [~ # ~]

EJBs sind älter als CDI-Beans und ähneln in gewisser Weise CDI-Beans und sind in anderer Hinsicht sehr unterschiedlich. Der Hauptunterschied zwischen CDI-Beans und EJBs besteht darin, dass die EJBs:

  • Transaktion
  • Remote oder lokal
  • Kann Stateful Beans passivieren und Ressourcen freisetzen
  • Kann Timer verwenden
  • Kann asynchron sein

Die beiden Arten von EJBs werden als zustandslos und zustandsbehaftet bezeichnet. Zustandslose EJBs können als thread-sichere Single-Use-Beans betrachtet werden, die zwischen zwei Webanforderungen keinen Status beibehalten. Stateful EJBs halten den Status und können so lange erstellt und verwendet werden, bis sie entsorgt werden.

Das Definieren eines EJB ist einfach. Fügen Sie der Klasse einfach eine Anmerkung javax.ejb.Stateless oder javax.ejb.Stateful hinzu.

@Stateless
public class BookingService {

  public String makeReservation(Item Item, Customer customer) {
    ...
    ...
  }
}

Stateless-Beans müssen einen abhängigen Bereich haben, während ein Stateful-Session-Bean einen beliebigen Bereich haben kann. Standardmäßig handelt es sich um Transaktionen, Sie können jedoch die Transaktionsattributanmerkung verwenden.

Während sich EJBs und CDI-Beans hinsichtlich der Funktionen stark unterscheiden, ist das Schreiben des Codes für die Integration sehr ähnlich, da CDI-Beans in EJBs und EJBs in CDI-Beans injiziert werden können. Es ist nicht erforderlich, einen Unterschied zu machen, wenn man einen in den anderen injiziert. Auch hier werden die verschiedenen Bereiche von CDI mithilfe von Proxys verwaltet. Eine Ausnahme ist, dass CDI das Injizieren von Remote-EJBs nicht unterstützt, dies jedoch durch Schreiben einer einfachen Producer-Methode implementiert werden kann.

Die Annotation javax.inject.Named sowie alle Qualifiers können in einem EJB verwendet werden, um sie einem Injektionspunkt zuzuordnen.

Wann soll man welche Bohne verwenden

Woher wissen Sie, wann welche Bohne verwendet werden muss? Einfach.

Verwenden Sie niemals JSF-verwaltete Beans, es sei denn, Sie arbeiten in einem Servlet-Container und möchten nicht versuchen, CDI in Tomcat zum Laufen zu bringen (obwohl es dafür einige Maven-Archetypen gibt, gibt es keine Entschuldigung).

Im Allgemeinen sollten Sie CDI-Beans verwenden, es sei denn, Sie benötigen die in den EJBs verfügbaren erweiterten Funktionen, z. B. Transaktionsfunktionen. Sie können Ihren eigenen Interceptor schreiben, um CDI-Beans transaktional zu machen. Derzeit ist es jedoch einfacher, einen EJB zu verwenden, bis CDI-Transaktions-CDI-Beans vor der Tür steht. Wenn Sie in einem Servlet-Container stecken bleiben und CDI verwenden, sind entweder handschriftliche Transaktionen oder Ihr eigener Transaktions-Interceptor die einzige Option ohne EJBs.

Wenn Sie @ViewScoped in CDI verwenden müssen, sollten Sie

  • benutze Nahtflächen oder MyFaces CODI Modul. Füge einfach einen davon zu deinem Klassenpfad hinzu und @ViewScoped wird in CDI funktionieren. MyFaces CODI wird von @ViewScoped noch besser unterstützt
  • benutze MyFaces CODI's @ViewAccessScoped, es ist eine Erweiterung, die von Apache auf CDI geschrieben wurde, nur download und benutze @ViewAccessScoped annotation anstelle von @ViewScoped.
  • Verwenden Sie CDI @ConversationScoped und sorgen Sie für eine lange Laufzeit. Siehe hier für mehr Infos .
  • Verwenden Sie Omnifaces @ViewScoped Annotation

Einige Teile stammen von hier .

189
Heidarzadeh

Ja, das kann verwirrend sein.

Aus ehm historischen Gründen verwenden JSF und CDI die gleichen Annotationen für Bereiche, jedoch aus unterschiedlichen Paketen.

Wie Sie wahrscheinlich erraten, die von javax.faces.bean stammen aus der JSF-Spezifikation und beziehen sich nicht auf CDI. Verwenden Sie sie nur, wenn Sie einen guten Grund dafür haben. Und mische sie niemals mit CDI-Annotationen von javax.ejb. Dies wird eine endlose Liste von Fehlern und subtilen Anomalien produzieren.

Generell empfehle ich Ihnen, die ersten paar (oder noch mehr) Seiten der ausgezeichneten Schweißdokumentation zu überfliegen. Dies sollte Sie auf den Weg bringen für Java EE 6.

Hier können Sie weitere Fragen stellen.

6
jan groth

Da es keine speziellen Antworten zu @javax.annotation.ManagedBean Gibt, finden Sie hier einen Link zur Antwort auf eine ähnliche Frage: Backing Beans (@ManagedBean) oder CDI Beans (@Named)? . Die Spezifikation finden Sie unter http://download.Oracle.com/otndocs/jcp/managed_beans-1.0-fr-eval-oth-JSpec/ . So scheint es mir, dass @javax.annotation.ManagedBean Eine Verallgemeinerung von @javax.faces.bean.ManagedBean Sein sollte.

Soweit ich weiß, werden JSF Managed Beans zugunsten von CDI Beans aus dem Markt genommen (möglicherweise wird sie von JSF 2.3 abgelehnt?). Ich denke, @javax.annotation.ManagedBean Ist jetzt umso veralteter.

1
Hein Blöd