Guía Completa del Ciclo de Vida de un Bean en Spring

En Spring, el ciclo de vida de un bean se puede manejar tanto mediante configuración basada en anotaciones como mediante configuración XML. En esta guía, veremos cómo manejar ambos enfoques, primero a través de anotaciones y luego con XML, para gestionar el ciclo de vida de los beans. Ambas configuraciones siguen el mismo ciclo de vida, pero su implementación varía.

Fases del Ciclo de Vida de un Bean

  1. Creación del Bean
  2. Inyección de Dependencias
  3. Inicialización del Bean
  4. Destrucción del Bean

Configuración con Anotaciones

1. Creación del Bean

Con Spring, podemos definir beans mediante la anotación @Component para clases que deben ser gestionadas por el contenedor de Spring.

Ejemplo usando anotaciones:

import org.springframework.stereotype.Component;

@Component
public class MyBean {
    public MyBean() {
        System.out.println("MyBean creado.");
    }
}

El contenedor de Spring detectará el bean MyBean gracias a la anotación @Component, y se encargará de su creación cuando se inicie el contexto de la aplicación.

2. Inyección de Dependencias

La inyección de dependencias también se puede realizar con anotaciones como @Autowired.

Ejemplo de inyección por constructor usando anotaciones:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MyService {

    private final MyBean myBean;

    @Autowired
    public MyService(MyBean myBean) {
        this.myBean = myBean;
        System.out.println("MyService creado.");
    }
}

3. Inicialización del Bean

Para inicializar un bean, podemos usar la anotación @PostConstruct, que ejecuta un método después de que las dependencias hayan sido inyectadas.

Ejemplo de inicialización usando @PostConstruct:

import javax.annotation.PostConstruct;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    @PostConstruct
    public void init() {
        System.out.println("Método de inicialización ejecutado.");
    }
}

4. Destrucción del Bean

Para destruir un bean antes de que se cierre el contexto de Spring, podemos utilizar la anotación @PreDestroy.

Ejemplo de destrucción usando @PreDestroy:

import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    @PreDestroy
    public void cleanup() {
        System.out.println("Método de destrucción ejecutado.");
    }
}

Configuración del Contexto de Spring con Anotaciones

Para configurar el contenedor de Spring con anotaciones, usamos la anotación @Configuration en una clase para indicar que esta clase es una configuración de Spring.

Ejemplo de configuración con anotaciones:

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.ejemplo")
public class AppConfig {
    // La anotación @ComponentScan detecta y registra los beans en el paquete especificado
}

Clase Principal con Spring Boot

El contenedor de Spring se inicia en una clase principal utilizando AnnotationConfigApplicationContext o SpringApplication.run en una aplicación Spring Boot.

Ejemplo de clase principal:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}

Configuración con XML

Ahora, veamos cómo se realiza la misma configuración, pero usando XML.

1. Creación del Bean

En XML, los beans se definen dentro de un archivo de configuración como applicationContext.xml mediante la etiqueta <bean>.

Ejemplo de creación de un bean en XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myBean" class="com.ejemplo.MyBean"/>
</beans>

2. Inyección de Dependencias

La inyección de dependencias también puede configurarse en XML utilizando el atributo ref.

Ejemplo de inyección por constructor en XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myBean" class="com.ejemplo.MyBean"/>
    <bean id="myService" class="com.ejemplo.MyService">
        <constructor-arg ref="myBean"/>
    </bean>
</beans>

3. Inicialización del Bean

En XML, podemos definir métodos de inicialización utilizando el atributo init-method.

Ejemplo de inicialización en XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myBean" class="com.ejemplo.MyBean" init-method="init"/>
</beans>

4. Destrucción del Bean

Al igual que la inicialización, la destrucción de beans también se configura en XML con el atributo destroy-method.

Ejemplo de destrucción en XML:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myBean" class="com.ejemplo.MyBean" destroy-method="cleanup"/>
</beans>

Configuración del Contexto de Spring con XML

El contexto de Spring se configura a través de un archivo XML donde se definen todos los beans. Al igual que en la configuración basada en anotaciones, los beans se registran en el contenedor.

Ejemplo de archivo applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myBean" class="com.ejemplo.MyBean"/>
    <bean id="myService" class="com.ejemplo.MyService">
        <constructor-arg ref="myBean"/>
    </bean>
</beans>

Clase Principal con Spring

Para cargar el contexto en una aplicación basada en XML, se utiliza ClassPathXmlApplicationContext.

Ejemplo de clase principal con XML:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApplication {

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        MyService myService = context.getBean("myService", MyService.class);
    }
}

Resumen

En Spring, el ciclo de vida de un bean es gestionado tanto por configuración basada en anotaciones como por configuración XML. En ambos casos, el ciclo de vida sigue las mismas etapas: creación, inyección de dependencias, inicialización y destrucción. Sin embargo, la forma de definir y configurar los beans varía según el enfoque elegido.

Ambas configuraciones permiten utilizar métodos personalizados de inicialización y destrucción, así como inyección de dependencias a través de constructores o setters.


Ejercicios para Practicar

Ejercicio 1: Crear un Bean con Inicialización y Destrucción en XML

Ejercicio 2: Inyección de Dependencias con XML y Anotaciones

Ejercicio 3: Configurar un Bean con Scope prototype

Ejercicio 4: Configurar un Bean con @PostConstruct y @PreDestroy en una Clase con Configuración Anotada