¿Cuál es la diferencia entre @ApplicationScoped y @Singleton scopes en CDI?

92

En CDI existe el @ApplicationScopedy el pseudo-alcance ( javax.inject) @Singleton. ¿Cuál es la diferencia entre ellos? Además del hecho de que @ApplicationScopedes proxy y @Singletonno lo es.

¿Puedo cambiar mi @Singletonfrijol a @ApplicationScoped? ¿Puede @ApplicationScopedbean tener dos (o más) instancias?

amorfis
fuente
11
¿Ha leído la referencia de soldadura ? Hay alguna explicación sobre las diferencias prácticas entre @ApplicationScopedy @Singletonen su sección 5.4 (p. 36).
brandizzi
3
También encuentro útil el resumen de diferencias al final de este artículo germanescobar.net/2010/04/…
matt freake
1
¿A qué alcance Singleton se refiere, javax.ejb o javax.inject?
John Ament

Respuestas:

29

@Singletonno forma parte de la especificación CDI. Es parte de EJB y javax.inject(JSR-330). No se menciona en la especificación cuál es su comportamiento, por lo que solo puede confiar en lo que está escrito en la documentación de Weld.

Bozho
fuente
11
Eso no es cierto. Hay una anotación javax.inject.Singleton. Es parte de CDI. Consulte aquí: docs.jboss.org/weld/reference/1.0.1-Final/en-US/html_single/…
amorfis
5
@amorphis: tengo la especificación CDI frente a mí. Incluso he implementado partes de él y no menciona nada al respecto @Singleton. Se muestra en un solo ejemplo, sin aclaraciones. Es cierto que CDI se basa en javax.inject, pero estrictamente hablando, no es parte de la especificación CDI. Dicho esto, corrigí un poco mi respuesta.
Bozho
17

en resumen: incluso puedes mezclarlo ( @Singletony @ApplicationScoped) y tiene sentido en algunos escenarios. (¡y funciona como se esperaba en el mío!)

Además de las otras respuestas hasta ahora, me gustaría agregar algunos puntos más para aclarar en escenarios del mundo real.

Para mí, esta pregunta se desarrolló a partir de ¿Cómo obligo a un bean de ámbito de aplicación a crear una instancia al iniciar la aplicación? En alguna discusión allí dije esto y no puedo encontrar un argumento válido en su contra hasta ahora:

En muchos escenarios / configuraciones de la vida real, diría que es difícil decir definitivamente, desde un punto de vista abstracto / de modelado, si algo es (o se convertirá / será tratado como) un EJB o un bean administrado de ámbito de aplicación.

argumentos (discutibles pero no concluyentes) (desde mi punto de vista) en su contra hasta ahora: (@BalusC y todos los demás: me gustaría verlos siendo concluyentes, pero si no, lo anterior puede ser cierto y, sin embargo, los argumentos pueden todavía ayudar al lector a obtener las diferencias / ventajas / desventajas / malas / buenas prácticas)

EJB frente a Bean gestionado

BalusC : Eso es un EJB, no un bean administrado, que es bastante diferente. Los EJB se ejecutan en el backend y los beans administrados en el frontend. Los EJB también se ejecutan en un contexto transaccional. [...] Acabas de confundir los beans enterprise con los beans gestionados y acabo de señalar eso.

pero:

Yo : Creo que no está del todo en lo correcto y exagera el significado / uso y me parece discutible. http://en.wikipedia.org/wiki/Enterprise_JavaBeans

Enterprise JavaBeans (EJB) es un software de servidor administrado para la construcción modular de software empresarial y una de las varias API de Java. EJB es un componente de software del lado del servidor que encapsula la lógica empresarial de una aplicación.

Tipos de Enterprise Beans

Session Beans [3] que pueden ser "Stateful", "Stateless" o "Singleton" [...]

Beans controlados por mensaje [...]

... que todavía es cierto en mi caso.

Singleton EJB vs.Bean con ámbito de aplicación

Cierre

BalusC : un EJB singleton no es lo mismo que un bean con ámbito de aplicación. Un EJB singleton está bloqueado en lectura / escritura y, por lo tanto, es potencialmente ineficiente / complicado para la tarea que tenía en mente. Para resumir: coge un buen libro de Java EE y aprende a utilizar la herramienta adecuada para el trabajo. Una forma definitivamente no es la otra. Que funcione no significa que sea la herramienta adecuada. Un mazo es capaz de apretar un tornillo, pero no es necesariamente la herramienta adecuada para eso :)

pero:

(No puedo ver el mazo aquí, lo siento ...) Es bueno saber los valores predeterminados de bloqueo (no lo sabía), pero esto parece ser incorrecto nuevamente: Tutorial de Oracle Java EE 6 sobre la administración del acceso concurrente en un Bean de sesión singleton

Al crear un bean de sesión singleton, el acceso simultáneo a los métodos comerciales del singleton se puede controlar de dos formas: concurrencia administrada por contenedor y concurrencia administrada por bean. [...]

Aunque de forma predeterminada, los singleton utilizan la concurrencia administrada por contenedor, la anotación @ConcurrencyManagement (CONTAINER) se puede agregar al nivel de clase del singleton para establecer explícitamente el tipo de administración de concurrencia

Andreas Dietrich
fuente
Weld no se divierte mezclando: Excepción al cargar la aplicación: Fallo de definición de CDI: WELD-000046: Como máximo, se puede especificar un alcance en [EnhancedAnnotatedTypeImpl] público ApplicationScoped Singleton MyClass. Utilizando javax.inject.Singleton.
sgflt
11

Por lo general, cuando desea tener solo una instancia de algún objeto, probablemente debería usar la @ApplicationScopedanotación; dicho objeto es proxy y, por lo tanto, incluso se puede serializar correctamente de forma inmediata.

Por otro lado, también hay muchos casos en los que solo desea una instancia de la clase, pero dicha clase no puede ser sustituida por proxy (por ejemplo, debido a que es final), entonces @Singletones un rescate. Porque Singletones un pseudo-alcance y no se está utilizando como proxy como cualquier alcance "normal".

G. Demecki
fuente
Estoy rechazando esto porque no está muy claro. He estado codificando en Java EE durante cinco años, tomando tutoriales y leyendo libros, pero no tengo una idea clara de lo que quiere decir cuando dice "dicho objeto es proxy", "incluso puede serializarse correctamente" y "pseudo- alcance". Me encantaría saber qué significa esto, ya que parece que sabes de lo que estás hablando, pero tal como está escrito, no puedo imaginar que tu respuesta ayude a la mayoría de los desarrolladores de Java EE.
DavidS
2
Dicho esto, sé que los EJB son proxy. Mi confusión se debe en parte a la distinción que está haciendo para Singletons.
DavidS
9

@Singletonen JSR-299 se refiere a beans de sesión Singleton ( javax.ejb.Singleton, no javax.inject.Singleton), no a beans administrados JSR-299 en un ámbito integrado llamado Singleton.

Puede encontrar en su servidor que @ApplicationScopedsea ​​uno por EAR o uno por WAR / EJB-JAR, ya que no está claro en la especificación, pero definitivamente no debe esperar que sea uno por JVM.

pagador
fuente
7

Hay una diferencia más: @Singletonno es un bean que define anotaciones, ya que el Singletonalcance no es un alcance normal. Entonces @ApplicationScopedes el frijol que define las anotaciones.

Con la especificación CDI 1.1: cuando la aplicación en modo de descubrimiento = anotado, Weld no identifica los beans con @Singletony no carga este

vigor
fuente
2

Una de las principales diferencias que puede escribir su clase con el constructor predeterminado tiene un modificador de acceso privado cuando se usa javax.inject.Singleton, pero su clase debe tener un constructor predeterminado con al menos un modificador de acceso predeterminado cuando se usa javax.enterprise.context.ApplicationScopedy esta es la JBOSS 6.1 GA Finalimplementación

usuario1017344
fuente
¿Quiso decir "constructor predeterminado"?
Treefish Zhang