Quelle est la différence entre les portées @ApplicationScoped et @Singleton dans CDI?

92

Dans CDI, il y a la pseudo-portée @ApplicationScopedet la ( javax.inject) @Singleton. Quelle est la différence entre eux? Outre le fait qui @ApplicationScopedest mandaté, et @Singletonne l'est pas.

Puis-je simplement changer mon @Singletonharicot en @ApplicationScoped? Le @ApplicationScopedbean peut-il avoir deux instances (ou plus)?

Amorfis
la source
11
Avez-vous lu la référence Weld ? Il y a quelques explications sur les différences pratiques entre @ApplicationScopedet @Singletonà sa section 5.4 (p. 36).
brandizzi
3
Je trouve aussi le résumé des différences à la fin de cet article germanescobar.net/2010/04/… utile
matt freake
1
à quelle portée Singleton faites-vous référence - javax.ejb ou javax.inject?
John Ament

Réponses:

29

@Singletonne fait pas partie de la spécification CDI. Il fait partie d'EJB et javax.inject(JSR-330). Il n'est pas mentionné dans la spécification quel est son comportement, vous ne pouvez donc vous fier qu'à ce qui est écrit dans la documentation Weld.

Bozho
la source
11
Ce n'est pas vrai. Il y a l'annotation javax.inject.Singleton. Cela fait partie du CDI. Vérifiez ici: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis
5
@amorphis - J'ai la spécification CDI devant moi. J'en ai même mis en œuvre certaines parties, et il ne mentionne rien à ce sujet @Singleton. Il n'est montré que dans un seul exemple, sans clarification. Il est vrai que CDI s'appuie sur javax.inject, mais à proprement parler, cela ne fait pas partie de la spécification CDI. Cela dit, j'ai corrigé un peu ma réponse.
Bozho
17

en bref: vous pouvez même le mélanger ( @Singletonet @ApplicationScoped) et cela a du sens dans certains scénarios. (et fonctionne comme prévu dans le mien!)

En plus des autres réponses jusqu'à présent, j'aimerais ajouter quelques points supplémentaires pour clarifier les scénarios du monde réel.

Pour moi, cette question a été développée à partir de Comment forcer un bean d'application à instancier au démarrage de l'application? Dans une discussion là-bas, j'ai déclaré ceci et je ne peux pas trouver d'argument valable contre cela jusqu'à présent:

Dans de nombreux scénarios / configurations de la vie réelle, je dirais qu'il est difficile de dire avec certitude - d'un point de vue abstrait / modélisation - si quelque chose est (ou deviendra / sera traité comme) un EJB ou un bean géré à portée d'application.

Arguments (discutables mais non concluants) (de mon point de vue) contre cela jusqu'à présent: (@BalusC et tous les autres: j'aimerais qu'ils soient concluants, mais sinon, ce qui précède peut être vrai et néanmoins les arguments peuvent aider encore le lecteur à obtenir les différences / avantages / inconvénients / mauvaises / bonnes pratiques)

EJB contre Managed Bean

BalusC : C'est un EJB pas un bean géré, ce qui est assez différent. Les EJB s'exécutent en backend et les beans gérés en frontend. Les EJB fonctionnent également dans un contexte transactionnel. [...] Vous venez de confondre les beans enterprise avec les beans gérés et je viens de le souligner.

mais:

moi : Je pense que vous n'êtes pas tout à fait correct et surestimez le sens / l'utilisation et cela me semble discutable. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) est un logiciel serveur géré pour la construction modulaire de logiciels d'entreprise et l'une des nombreuses API Java. EJB est un composant logiciel côté serveur qui encapsule la logique métier d'une application.

Types de beans entreprise

Session Beans [3] qui peut être "Stateful", "Stateless" ou "Singleton" [...]

Beans pilotés par message [...]

... ce qui est toujours vrai dans mon cas.

EJB Singleton et Bean de portée d'application

Verrouillage

BalusC : Un EJB singleton n'est pas la même chose qu'un bean de portée d'application. Un EJB singleton est verrouillé en lecture / écriture et donc potentiellement inefficace / surconvolué pour la tâche que vous aviez en tête. En bref: prenez un bon livre sur Java EE et apprenez à utiliser le bon outil pour le travail. Une façon n'est certainement pas l'autre. Que cela fonctionne ne signifie pas que c'est le bon outil. Une masse est capable de fixer une vis, mais ce n'est pas forcément le bon outil pour cela :)

mais:

(Je ne peux pas voir le marteau ici - désolé ...) Il est bon de connaître les paramètres de verrouillage par défaut (je n'en étais pas au courant), mais cela semble à nouveau incorrect: Oracle Java EE 6 Tutorial on Managing Concurrent Access in a Haricot de session singleton

Lors de la création d'un bean session singleton, l'accès simultané aux méthodes métier du singleton peut être contrôlé de deux manières: la concurrence gérée par le conteneur et la concurrence gérée par le bean. [...]

Bien que par défaut, les singletons utilisent la concurrence gérée par le conteneur, l'annotation @ConcurrencyManagement (CONTAINER) peut être ajoutée au niveau de la classe du singleton pour définir explicitement le type de gestion de la concurrence.

Andreas Dietrich
la source
Weld ne s'amuse pas en mélangeant: Exception lors du chargement de l'application: Échec de la définition CDI: WELD-000046: Au plus une portée peut être spécifiée sur [EnhancedAnnotatedTypeImpl] public ApplicationScoped Singleton MyClass. Utilisation de javax.inject.Singleton.
sgflt
11

Habituellement, lorsque vous ne voulez avoir qu'une seule instance d'un objet, vous devriez probablement utiliser l' @ApplicationScopedannotation - un tel objet est mandaté et peut donc même être correctement sérialisé prêt à l' emploi .

D'un autre côté, il y a aussi de nombreux cas où vous ne voulez qu'une seule instance de la classe, mais une telle classe ne peut pas être mandatée (par exemple parce qu'elle est définitive) - alors @Singletonest un sauvetage. Car Singletonest une pseudo-portée et n'est pas mandatée comme toute portée "normale".

G. Demecki
la source
Je vote défavorablement parce que ce n'est pas clair. J'ai codé en Java EE pendant cinq ans, suivi des didacticiels et lu des livres, mais je n'ai aucune idée précise de ce que vous voulez dire quand vous dites "un tel objet est mandaté", "peut même être correctement sérialisé" et "pseudo- portée". J'aimerais savoir ce que cela signifie, car il semble que vous savez de quoi vous parlez, mais tel qu'il est écrit, je ne peux pas imaginer que votre réponse aidera la plupart des développeurs Java EE.
DavidS
2
Cela dit, je sais que les EJB sont mandatés. Ma confusion tient en partie à la distinction que vous faites pour les Singletons.
DavidS
9

@Singletondans JSR-299 fait référence aux beans session Singleton ( javax.ejb.Singleton, pas javax.inject.Singleton), et non aux beans gérés JSR-299 dans une portée intégrée appelée Singleton.

Vous pouvez trouver dans votre serveur @ApplicationScopedun par EAR ou un par WAR / EJB-JAR car cela n'est pas clair dans la spécification, mais vous ne devez certainement pas vous attendre à ce qu'il en soit un par JVM.

couvreur
la source
7

Il y a une autre différence: le @Singletonbean ne définit pas les annotations, car la Singletonportée n'est pas une portée normale. Ensuite, le @ApplicationScopedbean définit les annotations.

Avec la spécification CDI 1.1: lorsque l'application en mode découverte = annotée, Weld n'identifie pas les beans avec @Singletonet ne les charge pas

vigueur
la source
2

L'une des principales différences que vous pouvez écrire dans votre classe avec le constructeur par défaut a un modificateur d'accès privé lors de l'utilisation javax.inject.Singleton, mais votre classe doit avoir un constructeur par défaut avec au moins un modificateur d'accès par défaut lors de l'utilisation javax.enterprise.context.ApplicationScopedet c'est l' JBOSS 6.1 GA Finalimplémentation

utilisateur1017344
la source
Vouliez-vous dire «constructeur par défaut»?
Treefish Zhang