Crea beans propios en Spring Boot sin estereotipos

Clase 12 de 31Curso de Java: Backend con Spring Boot

Contenido del curso

JPA con Spring y Spring Data

Resumen

Dominar la creación de dependencias propias en Spring Boot permite construir aplicaciones más flexibles y con una arquitectura limpia. En lugar de depender exclusivamente de estereotipos como @Service o @Component, es posible definir beans personalizados mediante la anotación @Configuration y el uso de @Bean, logrando un control total sobre las implementaciones que se inyectan en cada capa del proyecto.

¿Cómo crear un bean personalizado con interfaz e implementación?

El primer paso es organizar el proyecto correctamente. Se crea un paquete llamado bean donde se define una interfaz y su correspondiente implementación [0:22].

  • La interfaz MiBean declara un método void print().
  • La clase MiBeanImplement implementa esa interfaz y sobreescribe el método.

java public interface MiBean { void print(); }

java public class MiBeanImplement implements MiBean { @Override public void print() { System.out.println("Hola desde mi implementación propia del bean"); } }

A continuación, se crea un paquete configuration donde se centraliza toda la configuración de beans propios. La clase MiConfigurationBean se anota con @Configuration para indicarle a Spring Boot que contiene definiciones adicionales de dependencias [1:22].

java @Configuration public class MiConfigurationBean { @Bean public MiBean beanOperation() { return new MiBeanImplement(); } }

La anotación @Configuration marca una clase como fuente de definiciones de beans. Dentro de ella, cada método anotado con @Bean devuelve una instancia que Spring registra en su contenedor de dependencias. Se utiliza la palabra reservada new para instanciar la implementación concreta.

¿Por qué cambiar implementaciones es una ventaja arquitectónica?

Uno de los mayores beneficios de este enfoque es la capacidad de intercambiar implementaciones sin modificar el código que consume la dependencia [3:10]. Al crear una segunda clase MiBean2Implement, basta con cambiar la instancia en el archivo de configuración:

java @Bean public MiBean beanOperation() { return new MiBean2Implement(); }

En la clase FundamentosApplication, la inyección se realiza por constructor, y al ejecutar la aplicación el resultado cambia automáticamente sin tocar una sola línea del consumidor. Esto es lo que se conoce como inversión de control: el framework gestiona qué implementación concreta se entrega a cada componente.

¿Cómo inyectar una dependencia dentro de otra dependencia?

Spring Boot permite componer beans más complejos pasando una dependencia como parámetro de otra [4:25]. Para demostrarlo se crean dos nuevos elementos:

  • La interfaz MyOperation con un método int sum(int number).
  • La clase MyOperationImplement que suma uno al número recibido.

java public class MyOperationImplement implements MyOperation { @Override public int sum(int number) { return number + 1; } }

Después se define una interfaz MyBeanWithDependency y su implementación, que recibe MyOperation a través de su constructor [5:30]:

java public class MyBeanWithDependencyImplement implements MyBeanWithDependency { private final MyOperation myOperation;

public MyBeanWithDependencyImplement(MyOperation myOperation) { this.myOperation = myOperation; } @Override public void printWithDependency() { int number = 1; System.out.println(myOperation.sum(number)); System.out.println("Hola desde la implementación de un bean con dependencia"); }

}

¿Cómo se configura un bean que depende de otro bean?

En la clase de configuración, el método que registra el bean compuesto recibe la dependencia como parámetro. Spring resuelve automáticamente esa referencia desde su contenedor [6:45]:

java @Bean public MyBeanWithDependency beanOperationWithDependency(MyOperation myOperation) { return new MyBeanWithDependencyImplement(myOperation); }

Es fundamental que el tipo de retorno del método coincida con la interfaz, no con la clase concreta. Esto garantiza que Spring pueda resolver correctamente la inyección y evita errores de tipo en tiempo de compilación.

¿Qué resultado produce la inyección en cadena?

Al inyectar MyBeanWithDependency en FundamentosApplication y ejecutar el proyecto, la consola muestra el valor 2 —porque se envió 1 y la operación suma uno— seguido del mensaje de la implementación [8:12]. Esto confirma que la inyección de dependencias en cadena funciona correctamente: un bean consume otro bean sin acoplamiento directo entre clases concretas.

La sobreescritura de métodos mediante interfaces y la separación entre definición y configuración son pilares de este patrón. Cada pieza se puede probar, reemplazar o extender de forma independiente.

Si quieres practicar, crea tus propias dependencias con distintas implementaciones e inyéctalas en diferentes capas de la aplicación. Comparte tus resultados y dudas en la caja de comentarios.