CodeGym /Cursos /Módulo 5. Spring /Práctica: creación de clases de configuración y beans

Práctica: creación de clases de configuración y beans

Módulo 5. Spring
Nivel 2 , Lección 7
Disponible

Las clases de configuración en Java reemplazan el enfoque antiguo con configuración XML. Así convierten la configuración de aplicaciones Spring en un proceso más legible y cómodo.

Una clase de configuración es una clase Java que se usa para describir la configuración de tu aplicación. En Spring, estas clases se marcan con la anotación @Configuration. Eso le indica al contenedor IoC que la clase contiene métodos que crean beans. Esos métodos se marcan con la anotación @Bean.

Puedes imaginar la clase de configuración como el menú de tu cafetería favorita. Con @Bean describes qué se va a servir (objetos), y el contenedor IoC hace de camarero, entregando todo lo necesario (inyección de dependencias) a tu mesa.

Ejemplo de una clase de configuración sencilla


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

@Configuration
public class AppConfig {

    @Bean
    public String welcomeMessage() {
        return "¡Bienvenido a Spring Framework!";
    }
}

En nuestro ejemplo welcomeMessage es un bean que devuelve una cadena. La clase de configuración AppConfig contiene un método anotado con @Bean, y Spring sabe que ese método crea un bean gestionado por el contenedor IoC.

Pero no te preocupes, no nos vamos a quedar en un bean que solo te dice "hola". Vamos a darle caña y crear configuraciones más complejas.


Creación de beans y trabajo con dependencias

Las clases de configuración son útiles cuando creas objetos que tienen dependencias. Por ejemplo, si tenemos una clase Car que depende de un motor Engine, podemos configurarlo en la clase de configuración.

Ejemplo con dependencias


public class Engine {
    private String type;

    public Engine(String type) {
        this.type = type;
    }

    public String getType() {
        return type;
    }
}

public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }

    public void drive() {
        System.out.println("Car is driving with " + engine.getType() + " engine.");
    }
}

Ahora vamos a crear una clase de configuración para estos objetos:


@Configuration
public class VehicleConfig {

    @Bean
    public Engine engine() {
        return new Engine("V8");
    }

    @Bean
    public Car car() {
        return new Car(engine());
    }
}

En el método car llamamos al método engine para pasarlo al constructor de la clase Car. Esto permite a Spring entender que el bean Car depende del bean Engine. Ahora el contenedor IoC se encargará de configurar correctamente nuestro objeto.

¿Cómo funciona esto?

  1. Spring crea el bean Engine con el tipo V8.
  2. Luego se crea el bean Car, y en su constructor se inyecta automáticamente el bean Engine.

Este proceso cómodo reduce la cantidad de código que tendríamos que escribir a mano. Convengamos, a nadie le haría mucha gracia crear todas las dependencias manualmente.

Declaración explícita de dependencias entre beans

Si por alguna razón quieres indicarle explícitamente al bean Car que necesita el bean Engine, puedes hacerlo con la anotación @Qualifier (spoiler: te hará falta en las siguientes lecciones).


Dependencias complejas: beans que dependen de varios otros beans

Imagina que creamos un servicio de reserva de vuelos. Necesitamos combinar varias dependencias, como un cliente para la base de datos y un servicio de pagos. Todo eso se puede configurar en la clase de configuración.


public class PaymentService {
    public void pay() {
        System.out.println("¡Pago procesado con éxito!");
    }
}

public class BookingService {
    private PaymentService paymentService;

    public BookingService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void bookFlight() {
        System.out.println("Reserva completada.");
        paymentService.pay();
    }
}

Configuremos todo esto con una clase de configuración:


@Configuration
public class BookingConfig {

    @Bean
    public PaymentService paymentService() {
        return new PaymentService();
    }

    @Bean
    public BookingService bookingService() {
        return new BookingService(paymentService());
    }
}

Ahora obtenemos:

  • Encapsulación de la lógica de creación de objetos.
  • Minimización del código en la lógica principal de la aplicación.
  • Flexibilidad: los cambios en la configuración se adaptan con facilidad.

Evitando problemas por duplicación de beans

Uno de los errores más comunes es crear por accidente beans duplicados. Si intentas declarar dos beans con el mismo nombre, Spring lanzará un error: "Se han encontrado varios candidatos para la inyección de la dependencia". Para evitarlo, asegúrate de que tus métodos @Bean tengan nombres únicos y estén bien definidos.


Práctica: configurar un proyecto real

Hagamos un pequeño ejercicio relacionado con nuestra aplicación educativa. Vamos a crear un servicio para gestionar libros en una biblioteca, usando una clase de configuración.

Lógica de negocio


public class Book {
    private String title;
    private String author;

    public Book(String title, String author) {
        this.title = title;
        this.author = author;
    }

    @Override
    public String toString() {
        return "Book: " + title + " by " + author;
    }
}

public class LibraryService {
    private Book book;

    public LibraryService(Book book) {
        this.book = book;
    }

    public void displayBookInfo() {
        System.out.println(book.toString());
    }
}

Clase de configuración


@Configuration
public class LibraryConfig {

    @Bean
    public Book defaultBook() {
        return new Book("Clean Code", "Robert C. Martin");
    }

    @Bean
    public LibraryService libraryService() {
        return new LibraryService(defaultBook());
    }
}

Uso en la aplicación principal


import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Main {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(LibraryConfig.class);

        LibraryService libraryService = context.getBean(LibraryService.class);
        libraryService.displayBookInfo();
    }
}

Salida final del programa:


Book: Clean Code by Robert C. Martin

¡Enhorabuena! Hemos visto cómo usar clases de configuración y crear Spring Beans. Ahora puedes construir objetos, enlazar sus dependencias y hacer que el contenedor IoC trabaje para ti.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION