Introducción
Este tutorial muestra los diferentes ámbitos que se pueden asignar a un Bean o a un Componente en Spring Framework.
Es importante entender que la definición de un Bean no es más que una receta para crear instancias de una clase siguiendo la definición de esta receta. Esta receta puede ser luego utilizada una o más veces durante el ciclo de vida de la aplicación para crear una instancia del Bean.
El ámbito del Bean es una de las principales características de la configuración del Bean en Spring. El ámbito indicará cuándo y cómo se va a instanciar el objeto de la definición del Bean.
Spring incluye 7 ámbitos de Bean diferentes:
- Singleton
- Prototipo
- Solicitud
- Sesión
- Sesión global
- Aplicación
- Websocket
De estos, sólo 5 de ellos están disponibles en una aplicación web-aware.
Singleton
Singleton es el ámbito por defecto de un Bean, el que se utilizará si no se indica nada más. Este ámbito implica que el contenedor de Spring creará una única instancia compartida de la clase designada por este Bean, por lo que cada vez que se requiera el Bean se inyectará el mismo objeto. La instancia de este Bean se almacena en una caché gestionada por Spring.
Podemos utilizar anotaciones para definir singletons como en el siguiente ejemplo:
Como ya se ha indicado, Singleton es el ámbito por defecto de un Bean de Spring, por lo que no es necesario definir su @Scope
(primer ejemplo). Sin embargo, para mayor claridad y comprensión, se puede resaltar este hecho utilizando la anotación @Scope
como en el segundo ejemplo.
La siguiente prueba muestra el comportamiento de un singleton:
El comportamiento para las clases anotadas @Component
(o cualquiera de sus extensiones) es el mismo que para los Beans normales, serán singleton a menos que se configuren de otra manera.
Por ejemplo, un @RestController
como el siguiente:
Asegurará la siguiente prueba:
Prototipo
En el ámbito de Prototipo, el contenedor de Spring creará una nueva instancia del objeto descrito por el bean cada vez que reciba una petición. Una de las reglas básicas recogidas en la documentación de Spring es utilizar beans de ámbito Prototype cuando se trabaje en un entorno en el que haya gestión de sesiones (Stateful) y utilizar el ámbito Singleton cuando se trabaje en entornos sin gestión de sesiones (Stateless), sin embargo hay muchos más y diferentes casos de uso.
Es importante destacar que el contenedor de Spring no se responsabiliza de lo que ocurre con las instancias de los objetos recibidos al solicitar un bean. Esto significa que es tarea del desarrollador realizar la limpieza y liberación de los recursos referenciados por el objeto definido por el Bean.
Al igual que con el ámbito Singleton, podemos definir un bean con ámbito Prototype utilizando anotaciones de la siguiente manera::
1
2
3
4
5
|
@Bean(name = PROTOTYPE_BEAN_SAMPLE_NAME)
@Scope(SCOPE_PROTOTYPE)
public SamplePrototype() {
return new Sample();
}
|
La siguiente prueba muestra el comportamiento de un prototipo:
Singleton Beans con Prototype Beans inyectados
Es muy importante destacar que cuando se define un Singleton Bean con dependencias o Prototype Beans encapsulados, la inyección se produce cuando el objeto Singleton es instanciado por lo que la inyección sólo se produce una vez. Así, el objeto inyectado definido por el Bean Prototipo será siempre la misma instancia aunque se haya definido con un ámbito de Prototipo.
Por ejemplo, podemos definir una clase con un Bean inyectado de la siguiente manera:
Definimos los siguientes Beans:
El primer Bean (Sample
) tiene un ámbito Prototype y será inyectado en el segundo (SampleAutowired
) que tiene un ámbito Singleton. Como se ha explicado en los párrafos anteriores, el comportamiento esperado es que cada vez que solicitemos un SampleAutowired
, la instancia de Sample será la misma aunque tenga un ámbito Prototype porque fue instanciada y asignada una sola vez cuando SampleAutowired
(Singleton) fue instanciado por primera vez..
Esto se demuestra en la siguiente prueba:
Ámbitos de la aplicación web-aware
Como se ha mencionado en la introducción, el resto de ámbitos sólo están disponibles para las aplicaciones web-aware.
Request
El contenedor de Spring creará una nueva instancia del objeto definido por el Bean cada vez que reciba una petición HTTP.
Para definir un Bean con este alcance podemos utilizar las siguientes anotaciones dependiendo de si es un Bean o un Componente:
El comportamiento para el @RestController
del snippet anterior se puede probar de la siguiente manera:
Sesión
El contenedor de Spring creará una nueva instancia del objeto definido por el Bean para cada una de las sesiones HTTP (Stateful application) y devolverá esta misma instancia cada vez que reciba una petición dentro de la misma sesión.
El comportamiento para el @RestController
del snippet anterior se puede probar de la siguiente manera:
Sesión Global
El ámbito de la Sesión Global tiene un comportamiento similar al ámbito de la Sesión pero sólo es aplicable en el contexto de las aplicaciones web basadas en Portlet. La especificación Portlet define una sesión global como una sesión compartida entre todos los Portlets que componen una aplicación.
Si se utiliza este ámbito en una aplicación web normal, el comportamiento de los Beans definidos con este ámbito será el mismo que si se hubieran definido con un ámbito Session.
Application
El ámbito Application tiene un comportamiento muy similar al ámbito Singleton, Spring creará una nueva instancia del bean para cada ServletContext
. Una aplicación Spring puede tener varios ServletContext, por lo que la instancia devuelta por Spring para cada petición del Bean será la misma dentro del mismo contexto, pero diferente para cada uno de los contextos.
Websocket
El contenedor Spring creará una nueva instancia del objeto definido por el Bean y devolverá esta instancia para cada petición producida dentro del ciclo de vida de un Websocket.
Conclusión
.
0 comentarios