Was ist der Unterschied zwischen den Bereichen @ApplicationScoped und @Singleton in CDI?

90

In CDI gibt es das @ApplicationScopedund das ( javax.inject) @SingletonPseudo-Scope. Was ist der Unterschied zwischen ihnen? Neben der Tatsache, dass @ApplicationScopedProxy ist und @Singletonnicht.

Kann ich meine @SingletonBohne einfach ändern @ApplicationScoped? Kann @ApplicationScopedBean zwei (oder mehr) Instanzen haben?

Amorfis
quelle
11
Haben Sie die Schweißreferenz gelesen ? Es gibt einige Erklärungen zu den praktischen Unterschieden zwischen @ApplicationScopedund @Singletonin Abschnitt 5.4 (S. 36).
Brandizzi
3
Ich finde auch die Zusammenfassung der Unterschiede am Ende dieses Artikels germanescobar.net/2010/04/… nützlich
matt freake
1
Auf welchen Singleton-Bereich beziehen Sie sich - javax.ejb oder javax.inject?
John Ament

Antworten:

27

@Singletonist nicht Teil der CDI-Spezifikation. Es ist Teil von EJB und javax.inject(JSR-330). In der Spezifikation wird nicht erwähnt, wie es sich verhält, daher können Sie sich nur auf das verlassen, was in der Schweißdokumentation geschrieben steht.

Bozho
quelle
11
Das ist nicht wahr. Es gibt eine Anmerkung javax.inject.Singleton. Es ist Teil von CDI. Überprüfen Sie hier: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis
5
@amorphis - Ich habe die CDI-Spezifikation vor mir. Ich habe sogar Teile davon implementiert, und es wird nichts darüber erwähnt @Singleton. Es wird nur in einem Beispiel ohne Klarstellung gezeigt. Es ist wahr, dass CDI sich darauf verlässt javax.inject, aber genau genommen ist es nicht Teil der CDI-Spezifikation. Trotzdem habe ich meine Antwort etwas korrigiert.
Bozho
17

Kurz gesagt: Sie können es sogar mischen ( @Singletonund @ApplicationScoped) und es macht in einigen Szenarien Sinn. (und funktioniert wie erwartet in meinem!)

Zusätzlich zu den anderen bisherigen Antworten möchte ich einige weitere Punkte zur Verdeutlichung in realen Szenarien hinzufügen.

Für mich entstand diese Frage aus Wie erzwinge ich, dass eine Bean mit Anwendungsbereich beim Start der Anwendung instanziiert wird? In einigen Diskussionen dort habe ich dies festgestellt und kann bisher kein gültiges Argument dagegen finden:

In vielen realen Szenarien / Setups würde ich sagen, dass es aus abstrakter / modellistischer Sicht schwer zu sagen ist, ob etwas eine EJB oder eine anwendungsbezogene verwaltete Bean ist (oder werden wird / wird).

(umstrittene, aber nicht schlüssige) Argumente (aus meiner Sicht) bisher dagegen: (@BalusC und alle anderen: Ich würde gerne sehen, dass sie schlüssig sind, aber wenn nicht, kann das oben Gesagte zutreffen, und dennoch können die Argumente zutreffen helfen Sie dem Leser immer noch, die Unterschiede / Vor- / Nachteile / schlechten / guten Praktiken herauszufinden)

EJB vs. Managed Bean

BalusC : Das ist ein EJB, keine verwaltete Bohne, was ganz anders ist. EJBs werden im Backend ausgeführt und Beans im Frontend verwaltet. EJBs werden auch im Transaktionskontext ausgeführt. [...] Sie haben gerade Enterprise Beans mit Managed Beans verwechselt, und ich habe nur darauf hingewiesen.

aber:

Ich : Ich denke, Sie sind nicht ganz richtig und übertreiben die Bedeutung / Verwendung und es scheint mir fraglich. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) ist eine verwaltete Serversoftware für den modularen Aufbau von Unternehmenssoftware und eine von mehreren Java-APIs. EJB ist eine serverseitige Softwarekomponente, die die Geschäftslogik einer Anwendung kapselt.

Arten von Enterprise Beans

Session Beans [3], die entweder "Stateful", "Stateless" oder "Singleton" sein können [...]

Message Driven Beans [...]

... was in meinem Fall immer noch gilt.

Singleton EJB vs. Application Scoped Bean

Verriegeln

BalusC : Ein Singleton-EJB ist nicht dasselbe wie eine Bean mit Anwendungsbereich. Ein Singleton-EJB ist Lese- / Schreibsperre und daher möglicherweise ineffizient / überlastet für die von Ihnen geplante Aufgabe. Lange Rede, kurzer Sinn: Besorgen Sie sich ein gutes Java EE-Buch und lernen Sie, das richtige Tool für den Job zu verwenden. Ein Weg ist definitiv nicht der andere. Dass es funktioniert, bedeutet nicht, dass es das richtige Werkzeug ist. Ein Vorschlaghammer kann eine Schraube befestigen, aber es ist nicht unbedingt das richtige Werkzeug dafür :)

aber:

(Ich kann den Vorschlaghammer hier nicht sehen - Entschuldigung ...) Es ist gut, die Standardeinstellungen für das Sperren zu kennen (mir war dies nicht bekannt), aber dies scheint wieder falsch zu sein: Oracle Java EE 6-Lernprogramm zum Verwalten des gleichzeitigen Zugriffs in a Singleton Session Bean

Beim Erstellen einer Singleton-Session-Bean kann der gleichzeitige Zugriff auf die Geschäftsmethoden des Singletons auf zwei Arten gesteuert werden: durch Container verwaltete Parallelität und durch Bean verwaltete Parallelität. [...]

Obwohl Singletons standardmäßig die von Containern verwaltete Parallelität verwenden, kann die Annotation @ConcurrencyManagement (CONTAINER) auf Klassenebene des Singletons hinzugefügt werden, um den Typ der Parallelitätsverwaltung explizit festzulegen

Andreas Dietrich
quelle
Weld amüsiert sich nicht über das Mischen: Ausnahme beim Laden der App: CDI-Definitionsfehler: WELD-000046: In [EnhancedAnnotatedTypeImpl] public ApplicationScoped Singleton MyClass darf höchstens ein Bereich angegeben werden. Verwenden von javax.inject.Singleton.
sgflt
10

Wenn Sie nur eine Instanz eines Objekts haben möchten, sollten Sie normalerweise eine @ApplicationScopedAnnotation verwenden. Dieses Objekt wird als Proxy verwendet und kann daher sogar sofort ordnungsgemäß serialisiert werden.

Auf der anderen Seite gibt es auch viele Fälle, in denen Sie nur eine Instanz der Klasse möchten, diese Klasse jedoch nicht vertreten werden kann (z. B. weil sie endgültig ist) - dann @Singletonist dies eine Rettung. Weil Singletones sich um einen Pseudo-Bereich handelt und nicht wie ein "normaler" Bereich übertragen wird.

G. Demecki
quelle
Ich stimme dem zu, weil es sehr unklar ist. Ich habe fünf Jahre lang in Java EE programmiert, Tutorials genommen und Bücher gelesen, aber ich habe keine klare Vorstellung davon, was Sie meinen, wenn Sie sagen, dass "ein solches Objekt Proxy ist", "kann sogar ordnungsgemäß serialisiert werden" und "Pseudo-" Umfang". Ich würde gerne wissen, was das bedeutet, da es so klingt, als ob Sie wissen, wovon Sie sprechen, aber wie es geschrieben steht, kann ich mir nicht vorstellen, dass Ihre Antwort den meisten Java EE-Entwicklern helfen wird.
DavidS
2
Trotzdem weiß ich, dass EJBs vertreten sind. Meine Verwirrung liegt teilweise in der Unterscheidung, die Sie für Singletons machen.
DavidS
9

@Singletonin JSR-299 bezieht sich auf Singleton-Session-Beans ( javax.ejb.Singletonnicht javax.inject.Singleton), nicht auf JSR-299-verwaltete Beans in einem integrierten Bereich namens Singleton.

Möglicherweise finden Sie in Ihrem Server @ApplicationScopedeine pro EAR oder eine pro WAR / EJB-JAR, da dies in der Spezifikation nicht klar ist, aber Sie sollten definitiv nicht erwarten, dass es eine pro JVM ist.

Covener
quelle
7

Es gibt noch einen weiteren Unterschied: @SingletonDefiniert keine Bean-Annotationen, da der SingletonBereich kein normaler Bereich ist. Dann @ApplicationScopeddefiniert Bean Annotationen.

Mit CDI 1.1-Spezifikation: Wenn die Anwendung im Erkennungsmodus = kommentiert ist, identifiziert Weld Beans nicht mit dieser @Singletonund lädt sie nicht

Kraft
quelle
2

Einer der Hauptunterschiede, den Sie beim Schreiben Ihrer Klasse mit dem Standardkonstruktor machen können, ist der private Zugriffsmodifikator bei der Verwendung javax.inject.Singleton. Ihre Klasse sollte jedoch den Standardkonstruktor mit mindestens dem Standardzugriffsmodifikator bei der Verwendung haben. javax.enterprise.context.ApplicationScopedDies ist die JBOSS 6.1 GA FinalImplementierung

user1017344
quelle
Meinten Sie "Standardkonstruktor"?
Treefish Zhang