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

¡Hasta pronto 👋👍!

Comentarios

Entradas populares de este blog

JWT (Json Web Token)

Instalar Java Developmet Kit(JDK)

Curso de Spring