Alcance de Beans (Beans Scopes)
El alcance (scope) de beans determina si el contenedor Spring debe crear una instancia de una definición de bean cada vez que se inyecta o se solicita con getBean (…), o sí siempre tiene que devolver la misma instancia de bean.
Spring maneja varios scopes, vamos a revisar dos de ellos por ahora:
- singleton: (Predeterminado) Crea una única instancia para una definición de bean
- prototype: Crea una nueva instancia del bean cada vez que se inyecte o solicite.
Contenido
Scope Singleton
El contenedor Spring crea una única instancia para la definición de un bean. La instancia es almacenada en la cache del contenedor Spring, cada vez que se solicite con getBean (…) o sea referenciado mediante ref (inyección) , devolverá siempre la misma instancia de bean almacenada en cache del contenedor. La siguiente imagen muestra cómo funciona el alcance singleton:
El bean accountDao es inyectado varias veces en distintos beans, pero siempre es el mismo accountDao inyectado en todos.Los beans reciben simplemente una referencia hacia accountDao, por ende, si alguno de los beans que maneja accountDao, realiza una modificación sobre él, los demás beans también notaran la modificación, ya que todos manejan la misma instancia de accountDao. Similar cuando en java se utiliza campos static.
Scope Prototype
El contenedor Spring crea una nueva instancia por cada solicitud mediante getBean(..) o cuando es referenciado con ref (inyección). A diferencia del scope singleton, una vez que un bean prototype es entregado al cliente, el contenedor Spring no lleva mas registro del bean(no es almacenado en cache del contenedor). El siguiente diagrama ilustra el alcance del prototipo Spring:
En la imagen anterior, vemos como por cada inyección de accountDao en otro bean, se crea una nueva instancia de accountDao para ser inyectada. Cada bean maneja una instancia diferente de accountDao.
Como regla general, debe usar el ámbito prototipo para todos los beans con estado y el ámbito singleton para los beans sin estado.
Scope implementación
Mediante XML
<bean id="..." class="..." scope="singleton|prototype" />
Mediante Código Java
@Scope("singleton|prototype")
@Bean
pubic miObjeto ejemplo(){
....
}
Mediante anotaciones
@Scope("singleton|prototype")
@Component("miBeanEjemplo")
pubic class BeanEjemplo{
....
}
Los demás scopes (request, session, application) son implementados solo en aplicaciones Web, por ello los revisaremos es posteriores entradas. Puedes revisar la sección scopes de Spring.
Ejemplo
Vamos a trabajar con el proyecto de la entrada anterior app-persona. Hasta este punto del curso, todos los beans que hemos creado han sido de tipo singleton, independientemente se hayan creado mediante <bean>, @Bean o @Component.
Singleton
Tenemos los beans miDireccion y miPersona en el contenedor Spring, miDireccion en un dependencia del bean miPersona.
Vamos a obtener el bean miDireccion y modificaremos el valor del atributo numeroCasa.
public class TestPersona { public static void main(String [] args){ // ... Instancia del contenedor : context // Obtener bean miDireccion Direccion direccion = context.getBean("miDireccion", Direccion.class); direccion.setNumeroCasa(100); System.out.println(direccion.toString()); // ... Obtener bean miPersona : persona } }
Salida Consola
// Datos Direccion Direccion [callePrincipal=La Lorena y Pasaje, numeroCasa=100] // Datos Persona Persona [...] Direccion [callePrincipal=La Lorena y Pasaje, numeroCasa=100]
Puede notar como la direccion(numeroCasa) del bean persona tambien se modifico a 100. Esto se debe a que el bean miDireccion que se esta modificando, es el mismo bean miDireccion que se inyecto en miPersona desde el contenedor Spring.
Como se mencionó anteriormente, singleton crea una unica instancia de un bean, cada vez que se inyecte o se obtenga ese bean, devolverá siempre la misma instancia de bean.
Prototype
En el contenedor Spring, agregamos el atributo scope="prototype" al bean miDireccion
<bean id="miDireccion" class="..." scope="prototype" />
Si ejecutamos la clase principal TestPersona, notaremos el cambio
Salida Consola
// Datos Direccion Direccion [callePrincipal=La Lorena y Pasaje, numeroCasa=100] // Datos Persona Persona [...] Direccion [callePrincipal=La Lorena y Pasaje, numeroCasa=23]
Ahora vemos que la dirección(numeroCasa) del bean persona no cambia, ya que la direccion inyectada a persona desde el contenedor Spring y la direccion que se recupera y modifica en TestPersona son instancias distintas.
Descargar proyecto gitHub | scopes
Comentarios
Publicar un comentario