Guía Completa y Detallada: Spring Bean Scopes

Introducción a los Bean Scopes en Spring

En el marco de Spring, un Bean es un objeto gestionado por el contenedor de Spring. El contenedor es responsable de la creación, configuración y manejo del ciclo de vida de los Beans. Los Bean Scopes determinan la vida útil o el alcance de un Bean dentro del contenedor de Spring, es decir, cómo se gestionan las instancias de un Bean durante la ejecución de una aplicación.

Spring proporciona varios tipos de Scopes que se pueden configurar para cada Bean, dependiendo de la necesidad de la aplicación.

Tipos de Bean Scopes

1. Singleton (Alcance único)

Este es el scope por defecto en Spring. Un Singleton es una instancia única de un Bean en el contenedor de Spring. Es decir, solo se crea una única instancia del Bean durante toda la ejecución de la aplicación, y esta instancia es compartida por todas las clases que la necesiten.

Características:

Ejemplo:

@Component
public class MiBeanSingleton {

    public MiBeanSingleton() {
        System.out.println("Instancia de MiBeanSingleton creada");
    }

    public void saludar() {
        System.out.println("¡Hola desde el Bean Singleton!");
    }
}

En este ejemplo, el Bean MiBeanSingleton será creado una sola vez y será compartido en todo el ciclo de vida de la aplicación.

2. Prototype (Alcance prototipo)

Cuando un Bean tiene el scope de Prototype, Spring crea una nueva instancia del Bean cada vez que se solicita. Es decir, cada vez que se inyecta el Bean o se solicita mediante getBean(), se obtiene una nueva instancia.

Características:

Ejemplo:

@Component
@Scope("prototype")
public class MiBeanPrototype {

    public MiBeanPrototype() {
        System.out.println("Instancia de MiBeanPrototype creada");
    }

    public void saludar() {
        System.out.println("¡Hola desde el Bean Prototype!");
    }
}

En este caso, cada vez que se solicita MiBeanPrototype, se crea una nueva instancia del Bean.

3. Request (Alcance de solicitud)

Este scope es aplicable solo en aplicaciones basadas en web. Un Bean con el scope request será creado y destruido en el contexto de una única solicitud HTTP. Esto significa que cada vez que un cliente realiza una solicitud HTTP, se crea una nueva instancia del Bean y se destruye al final de la solicitud.

Características:

Ejemplo:

@Component
@Scope("request")
public class MiBeanRequest {

    public MiBeanRequest() {
        System.out.println("Instancia de MiBeanRequest creada");
    }

    public void saludar() {
        System.out.println("¡Hola desde el Bean Request!");
    }
}

4. Session (Alcance de sesión)

Similar al scope request, el scope session mantiene una instancia del Bean durante la duración de una sesión HTTP. Es decir, el Bean será creado en el inicio de la sesión del usuario y persistirá durante toda la vida de la sesión.

Características:

Ejemplo:

@Component
@Scope("session")
public class MiBeanSession {

    public MiBeanSession() {
        System.out.println("Instancia de MiBeanSession creada");
    }

    public void saludar() {
        System.out.println("¡Hola desde el Bean Session!");
    }
}

5. Application (Alcance de aplicación)

El scope application es similar al singleton, pero tiene un alcance a nivel de aplicación en lugar de ser limitado a una única instancia del contenedor. Esto es particularmente útil en aplicaciones web donde se desea compartir el Bean entre múltiples sesiones.

Características:

Ejemplo:

@Component
@Scope("application")
public class MiBeanApplication {

    public MiBeanApplication() {
        System.out.println("Instancia de MiBeanApplication creada");
    }

    public void saludar() {
        System.out.println("¡Hola desde el Bean Application!");
    }
}

6. Websocket (Alcance de WebSocket)

Este scope es para WebSockets en aplicaciones web en tiempo real. Un Bean con el scope websocket se crea para cada sesión de WebSocket.

Características:

¿Cómo configurar el Bean Scope?

El scope de un Bean se puede definir de diferentes maneras:

1. Mediante anotaciones:

Se utiliza la anotación @Scope junto con la anotación @Component, @Service, @Repository, etc.

@Component
@Scope("prototype")
public class MiBean {
    // ...
}

2. Mediante XML:

También se puede definir el scope dentro del archivo XML de configuración de Spring.

<bean id="miBean" class="com.ejemplo.MiBean" scope="prototype"/>

¿Cómo solicitar un Bean con un Scope específico?

Para obtener un Bean con un scope determinado, se puede usar el ApplicationContext de Spring.

ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
MiBean miBean = context.getBean(MiBean.class);

Dependiendo del scope configurado, Spring proporcionará la instancia correspondiente.

Consideraciones y Buenas Prácticas

Ejercicios

Ejercicio 1: Uso de singleton y prototype

  1. Crea dos Beans: uno con scope singleton y otro con scope prototype.
  2. Inyecta ambos Beans en una clase de prueba.
  3. Imprime la instancia de cada Bean y observa cuántas veces se crea la instancia.

Ejercicio 2: Bean con request y session

  1. Crea un Bean con el scope request y otro con el scope session.
  2. Configura una aplicación web sencilla con Spring y realiza varias solicitudes.
  3. Observa la creación de los Beans en los logs para ver cómo cambia la instancia en función de las solicitudes y sesiones.

Ejercicio 3: Application Scope en una Aplicación Web

  1. Crea un Bean con scope application y verifica que solo se crea una instancia en toda la aplicación.
  2. Desarrolla una pequeña aplicación web con varios usuarios y asegúrate de que la instancia del Bean no se crea varias veces.

Conclusión

Los Bean Scopes en Spring son esenciales para definir cómo se gestionan las instancias de un Bean. Comprender los diferentes scopes y cómo utilizarlos en función de las necesidades de la aplicación es clave para escribir aplicaciones eficientes y mantener un buen control del ciclo de vida de los Beans en el contenedor de Spring.