Qual è la differenza tra gli ambiti @ApplicationScoped e @Singleton in CDI?


92

In CDI c'è lo pseudo-ambito @ApplicationScopede ( javax.inject) @Singleton. Qual'è la differenza tra loro? Oltre al fatto che @ApplicationScopedè proxy e @Singletonnon lo è.

Posso semplicemente cambiare il mio @Singletonfagiolo in @ApplicationScoped? Il @ApplicationScopedbean può avere due (o più) istanze?


11
Hai letto il riferimento di saldatura ? C'è qualche spiegazione sulle differenze pratiche tra @ApplicationScopede @Singletonnella sua sezione 5.4 (p. 36).
brandizzi

3
Trovo anche il riassunto delle differenze, alla fine di questo articolo germanescobar.net/2010/04/... utile
matt Freake

1
a quale ambito Singleton ti riferisci: javax.ejb o javax.inject?
John Ament

Risposte:


29

@Singletonnon fa parte della specifica CDI. Fa parte di EJB e javax.inject(JSR-330). Non è menzionato nelle specifiche qual è il suo comportamento, quindi puoi fare affidamento solo su ciò che è scritto nella documentazione di Weld.


11
Non è vero. C'è l'annotazione javax.inject.Singleton. Fa parte di CDI. Controlla qui: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis

5
@amorphis - Ho la specifica CDI davanti a me. Ne ho persino implementato alcune parti e non menziona nulla @Singleton. È mostrato in un solo esempio, senza chiarimenti. È vero che il CDI fa affidamento javax.inject, ma in senso stretto non fa parte delle specifiche CDI. Detto questo, ho corretto un po 'la mia risposta.
Bozho

17

in breve: puoi persino mescolarlo ( @Singletone @ApplicationScoped) e ha senso in alcuni scenari. (e funziona come previsto nel mio!)

Oltre alle altre risposte finora, vorrei aggiungere altri punti per chiarimenti negli scenari del mondo reale.

Per me questa domanda è stata sviluppata da Come impongo a un bean con ambito applicazione di creare un'istanza all'avvio dell'applicazione? In alcune discussioni ho affermato questo e finora non riesco a trovare un argomento valido contro di esso:

In molti scenari / configurazioni di vita reale, direi che è difficile dire con certezza - da un punto di vista astratto / modellistico - se qualcosa è (o diventerà / sarà trattato come) un EJB o un bean gestito con ambito di applicazione.

argomenti (discutibili ma non conclusivi) (dal mio punto di vista) contro di esso finora: (@BalusC e tutti gli altri: mi piacerebbe vederli essere conclusivi, ma in caso contrario, quanto sopra potrebbe essere vero e tuttavia gli argomenti potrebbero aiutare ancora il lettore a capire le differenze / vantaggi / svantaggi / cattive / buone pratiche)

EJB vs Managed Bean

BalusC : Questo è un bean EJB non gestito, il che è molto diverso. Gli EJB vengono eseguiti nel backend e i bean gestiti nel frontend. Anche i bean bean vengono eseguiti in un contesto transazionale. [...] Hai appena confuso i bean enterprise con i bean gestiti e l'ho appena fatto notare.

ma:

io : Penso che tu non sia del tutto corretto e ne esageri il significato / utilizzo e mi sembra discutibile. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) è un software server gestito per la costruzione modulare di software aziendale e una delle numerose API Java. EJB è un componente software lato server che incapsula la logica di business di un'applicazione.

Tipi di fagioli aziendali

Session Beans [3] che possono essere "Stateful", "Stateless" o "Singleton" [...]

Message Driven Beans [...]

... che è ancora vero nel mio caso.

EJB Singleton e Bean con ambito applicazione

Blocco

BalusC : un EJB singleton non è la stessa cosa di un bean con ambito dell'applicazione. Un EJB singleton è bloccato in lettura / scrittura e quindi potenzialmente inefficiente / iperconvoluto per l'attività che avevi in ​​mente. Per farla breve: prendi un buon libro Java EE e impara a utilizzare lo strumento giusto per il lavoro. Un modo sicuramente non è l'altro. Che funzioni non significa che sia lo strumento giusto. Una mazza è in grado di fissare una vite, ma non è necessariamente lo strumento giusto per farlo :)

ma:

(Non riesco a vedere la mazza qui - scusa ...) È bello conoscere le impostazioni predefinite di blocco (non ne ero a conoscenza), ma sembra di nuovo non essere corretto: Oracle Java EE 6 Tutorial sulla gestione dell'accesso simultaneo in un Singleton Session Bean

Quando si crea un bean di sessione singleton, l'accesso simultaneo ai metodi di business del singleton può essere controllato in due modi: concorrenza gestita dal contenitore e concorrenza gestita dal bean. [...]

Sebbene per impostazione predefinita, i singleton utilizzino la concorrenza gestita dal contenitore, l'annotazione @ConcurrencyManagement (CONTAINER) può essere aggiunta a livello di classe del singleton per impostare in modo esplicito il tipo di gestione della concorrenza


La saldatura non è divertita dalla miscelazione: Eccezione durante il caricamento dell'app: Errore di definizione CDI: WELD-000046: È possibile specificare al massimo un ambito su [EnhancedAnnotatedTypeImpl] pubblico ApplicationScoped Singleton MyClass. Utilizzando javax.inject.Singleton.
sgflt

11

Di solito quando vuoi avere solo un'istanza di un oggetto, probabilmente dovresti usare l' @ApplicationScopedannotazione - tale oggetto è proxy e quindi può anche essere opportunamente serializzato fuori dalla scatola.

D'altra parte, ci sono anche molti casi in cui si desidera solo un'istanza della classe, ma tale classe non può essere proxy (ad esempio perché è definitiva) - quindi @Singletonè un salvataggio. Perché Singletonè uno pseudo-ambito e non viene sottoposto a proxy come un qualsiasi ambito "normale".


Sto downvoting questo perché non è molto chiaro. Scrivo codice in Java EE da cinque anni, seguo tutorial e leggo libri, ma non ho idea di cosa intendi quando dici "tale oggetto è proxy", "può anche essere serializzato correttamente" e "pseudo- scopo". Mi piacerebbe sapere cosa intendi con questo, poiché sembra che tu sappia di cosa stai parlando, ma come è scritto non riesco a immaginare che la tua risposta aiuterà la maggior parte degli sviluppatori Java EE.
DavidS

2
Detto questo, so che i bean sono proxy. La mia confusione è in parte intorno alla distinzione che stai facendo per Singletons.
DavidS

9

@Singletonin JSR-299 fa riferimento ai bean di sessione Singleton ( javax.ejb.Singleton, non javax.inject.Singleton), non ai bean gestiti JSR-299 in un ambito integrato chiamato Singleton.

Potresti trovare nel tuo server @ApplicationScopeduno per EAR o uno per WAR / EJB-JAR poiché non è chiaro nelle specifiche, ma non dovresti assolutamente aspettarti che sia uno per JVM.


7

C'è un'altra differenza: @Singletonnon è il bean che definisce le annotazioni, poiché lo Singletonscope non è uno scope normale. Quindi @ApplicationScopedè il bean che definisce le annotazioni.

Con specifica CDI 1.1: quando l'applicazione in modalità discovery = annotata, Weld non identifica i bean con @Singletone non lo carica


2

Una delle principali differenze che puoi scrivere la tua classe con il costruttore predefinito ha un modificatore di accesso privato quando lo usi javax.inject.Singleton, ma la tua classe dovrebbe avere un costruttore predefinito con almeno un modificatore di accesso predefinito quando lo usi javax.enterprise.context.ApplicationScopede questa è l' JBOSS 6.1 GA Finalimplementazione


Volevi dire "costruttore predefinito"?
Treefish Zhang
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.