Lassen Sie mich zunächst einige Klarstellungen vornehmen:
Definition einer verwalteten Bean: Im Allgemeinen ist eine verwaltete Bean ein Objekt, dessen Lebenszyklus (Konstruktion, Zerstörung usw.) von einem Container verwaltet wird.
In Java ee gibt es viele Container, die den Lebenszyklus ihrer Objekte verwalten, z. B. JSF-Container, EJB-Container, CDI-Container, Servlet-Container usw.
Alle diese Container arbeiten unabhängig voneinander. Sie booten in der Anwendungsserverinitialisierung und scannen Klassen aller Artefakte, einschließlich JAR-, EJB-JAR-, War- und Ear-Dateien, in der Bereitstellungszeit und sammeln und speichern einige Metadaten darüber, wenn Sie ein Objekt benötigen einer Klasse zur Laufzeit geben sie Ihnen Instanzen dieser Klassen und nach Beendigung des Jobs zerstören sie sie.
Wir können also sagen, dass wir:
- JSF verwaltete Beans
- CDI verwaltete Beans
- EJB verwaltete Bohnen
- Und selbst Servlets sind verwaltete Beans, weil sie von einem Container, einem Servlet-Container, instanziiert und zerstört werden.
Wenn Sie also das Managed Bean-Wort sehen, sollten Sie nach dem Kontext oder Typ des Wortes fragen (JSF, CDI, EJB usw.).
Dann könnten Sie sich fragen, warum wir viele dieser Container haben: AFAIK, Java EE-Leute wollten ein Abhängigkeitsinjektions-Framework, aber sie konnten nicht alle Anforderungen in einer Spezifikation erfassen, weil sie die zukünftigen Anforderungen nicht vorhersagen konnten und EJB 1.0 und dann erstellten 2.0 und dann 3.0 und jetzt 3.1, aber das Ziel von EJB waren nur einige Anforderungen (Transaktion, verteiltes Komponentenmodell usw.).
Gleichzeitig (parallel) erkannten sie, dass sie auch JSF unterstützen müssen, dann stellten sie JSF-verwaltete Beans und einen weiteren Container für JSF-Beans her und betrachteten es als 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, das ist der ausgereifteste DI-Container, 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, Herstellungsmethoden, Abfangjägern, Dekorateuren, Integrations-SPI, sehr flexibel usw. zu schließen Was EJB- und JSF-verwaltete Beans tun, können wir nur einen ausgereiften und leistungsstarken DI-Container haben. Aber aus Gründen der Abwärtskompatibilität und aus politischen Gründen wollen Java EE-Leute sie behalten !!!
Hier finden Sie den Unterschied und die Anwendungsfälle für jeden dieser Typen:
JSF Managed Beans, CDI Beans und EJBs
JSF wurde ursprünglich mit einem eigenen verwalteten Bean- und Abhängigkeitsinjektionsmechanismus entwickelt, der für JSF 2.0 um annotationsbasierte Beans erweitert wurde. Als CDI mit Java EE 6 veröffentlicht wurde, wurde es als verwaltetes Bean-Framework für diese Plattform angesehen, und natürlich haben EJBs sie alle veraltet, da es sie schon seit mehr als einem Jahrzehnt gibt.
Das Problem ist natürlich zu wissen, welche und wann sie verwendet werden sollen.
Beginnen wir mit den einfachsten, JSF Managed 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 die Abhängigkeitsinjektion und die Definition von Backing Beans für Webseiten, sind jedoch weitaus weniger leistungsfähig als CDI Beans.
Sie können mithilfe der @javax.faces.bean.ManagedBean
Anmerkung definiert werden, die einen optionalen Namensparameter verwendet. 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 im javax.faces.bean
Paket definierten Bereiche verwendet wird , einschließlich der Bereiche Anforderung, Sitzung, Anwendung, Ansicht und Benutzerdefiniert.
@ManagedBean(name="someBean")
@RequestScoped
public class SomeBean {
....
....
}
JSF-Beans können ohne manuelle Codierung nicht mit anderen Beansorten gemischt werden.
CDI Bohnen
CDI ist das Bean-Management- und Abhängigkeitsinjektions-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 einfache JSF-verwaltete Beans. Sie können Interceptors, Konversationsumfang, Ereignisse, typsichere Injektionen, Dekorateure, Stereotypen und Herstellungsmethoden verwenden.
Um CDI-Beans bereitzustellen, müssen Sie eine Datei mit dem Namen 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, zu viele, um sie hier zu behandeln. Als Kurzreferenz für JSF-ähnliche Funktionen können Sie den Umfang der CDI-Bean mithilfe eines der im javax.enterprise.context
Paket definierten Bereiche definieren (nämlich Anforderung, Konversation) , Sitzungs- und Anwendungsbereiche). Wenn Sie die CDI-Bean von einer JSF-Seite verwenden möchten, können Sie ihr mithilfe der javax.inject.Named
Anmerkung einen Namen geben . Um eine Bean in eine andere Bean einzufügen, kommentieren Sie das Feld mit javax.inject.Inject
Annotation.
@Named("someBean")
@RequestScoped
public class SomeBean {
@Inject
private SomeService someService;
}
Eine automatische Injektion wie die oben definierte kann durch die Verwendung von Qualifikatoren gesteuert werden, die dazu beitragen können, die spezifische Klasse zu erreichen, die Sie injizieren möchten. Wenn Sie mehrere Zahlungsarten haben, können Sie ein Qualifikationsmerkmal hinzufügen, ob es asynchron ist oder nicht. Sie können die @Named
Annotation zwar als Qualifikationsmerkmal verwenden, sollten dies jedoch nicht tun, da sie zum Anzeigen der Beans in EL bereitgestellt wird.
CDI behandelt 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 bei jeder 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 Konversationsbereich und viele andere Funktionen, was es zu einer viel besseren Wahl gegenüber von JSF verwalteten Beans macht.
EJB
EJBs sind älter als CDI-Beans und ähneln in gewisser Weise CDI-Beans und sind auf andere Weise sehr unterschiedlich. In erster Linie besteht der Unterschied zwischen CDI-Beans und EJBs darin, dass 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. Statuslose EJBs können als thread-sichere Single-Use-Beans betrachtet werden, die keinen Status zwischen zwei Webanforderungen beibehalten. Stateful EJBs halten den Status und können erstellt und so lange herumgesessen werden, wie sie benötigt werden, bis sie entsorgt werden.
Das Definieren eines EJB ist einfach. Fügen Sie der Klasse entweder eine javax.ejb.Stateless
oder eine javax.ejb.Stateful
Anmerkung hinzu.
@Stateless
public class BookingService {
public String makeReservation(Item Item, Customer customer) {
...
...
}
}
Statuslose Beans müssen einen abhängigen Bereich haben, während ein Stateful Session Bean einen beliebigen Bereich haben kann. Standardmäßig sind sie transaktional, Sie können jedoch die Annotation für Transaktionsattribute verwenden.
Während sich EJBs und CDI-Beans hinsichtlich der Funktionen stark unterscheiden, ist das Schreiben des Codes zum Integrieren sehr ähnlich, da CDI-Beans in EJBs und EJBs in CDI-Beans injiziert werden können. Es ist nicht erforderlich, beim Einspritzen in das andere zu unterscheiden. Auch hier werden die verschiedenen Bereiche von CDI mithilfe von Proxy behandelt. Eine Ausnahme hiervon ist, dass CDI die Injektion von Remote-EJBs nicht unterstützt, dies jedoch durch Schreiben einer einfachen Herstellermethode implementiert werden kann.
Die javax.inject.Named
Annotation sowie alle Qualifikationsmerkmale können auf einem EJB verwendet werden, um sie einem Injektionspunkt zuzuordnen.
Wann welche Bohne zu verwenden ist
Woher wissen Sie, wann Sie welche Bohne verwenden müssen? 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 transaktionale CDI-Beans erhält, die sich gleich um die Ecke befinden. Wenn Sie in einem Servlet-Container stecken bleiben und CDI verwenden, sind entweder handgeschriebene Transaktionen oder Ihr eigener Transaktions-Interceptor die einzige Option ohne EJBs.
Wenn Sie @ViewScoped
in CDI verwenden müssen, sollten Sie
- verwenden Nahtflächen oder MyFaces CODI Modul. Fügen Sie einfach einen davon zu Ihrem Klassenpfad hinzu und er
@ViewScoped
funktioniert in CDI. MyFaces CODI unterstützt @ViewScoped noch solider
- Verwenden Sie MyFaces CODIs. Dies
@ViewAccessScoped
ist eine Erweiterung, die von Apache auf CDI geschrieben wurde. Laden Sie sie einfach herunter und verwenden Sie @ViewAccessScoped
stattdessen Annotation @ViewScoped
.
- Verwenden Sie CDI
@ConversationScoped
und machen Sie es langlebig. Sehen Sie hier für weitere Informationen .
- Verwenden Sie die Annotation Omnifaces @ViewScoped
Einige Teile wurden von hier gestohlen .