Ahora vamos a ver las anotaciones en la práctica para que quede más claro.
1. Anotación @Component — la magia de crear beans
La anotación @Component convierte una clase Java normal en un Spring Bean que el contenedor IoC de Spring gestiona automáticamente. Es como si le dijeras a un agente especial llamado Spring: "Ocúpate de esta clase, crea su instancia e inyéctala cuando haga falta".
Por debajo, el contenedor IoC escanea las clases del proyecto mediante el mecanismo Component Scan, y busca todas las clases marcadas con @Component.
Ejemplo de uso de @Component
import org.springframework.stereotype.Component;
// Con la anotación indicamos que esta clase es un componente (bean)
@Component
public class CoffeeMaker {
public String makeCoffee() {
return "☕ ¡Café listo!";
}
}
Ahora CoffeeMaker está registrado en el contenedor IoC. Puedes obtenerlo donde quieras y Spring creará la instancia de esa clase por ti.
Analogía: si fueras el contenedor Spring, @Component sería la señal "Agrégalo a mi lista de responsabilidades".
2. Anotación @Autowired: el arte de la inyección de dependencias
Cuando marcamos algo con @Autowired, le decimos a Spring: "¡Busca y conecta el componente que haga falta tú mismo!". Spring busca el bean adecuado (por ejemplo, nuestro CoffeeMaker) y lo añade vía campo, constructor o setter.
Inyección por campo
Este modo es el más sencillo, pero tiene sus inconvenientes (ver "Errores típicos" abajo).
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Barista {
// Le decimos a Spring: "¡Inyecta aquí CoffeeMaker!"
@Autowired
private CoffeeMaker coffeeMaker;
public void serveCoffee() {
System.out.println(coffeeMaker.makeCoffee());
}
}
Marcando el campo con @Autowired indicamos a Spring que debe inicializarlo antes del primer uso. Ahora, cuando arranquemos la aplicación, Barista sabrá cómo servir el café.
Inyección por constructor
Forma recomendada: hace las dependencias "visibles" y facilita el testing.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Barista {
private final CoffeeMaker coffeeMaker;
// Spring llamará a este constructor y le pasará CoffeeMaker
@Autowired
public Barista(CoffeeMaker coffeeMaker) {
this.coffeeMaker = coffeeMaker;
}
public void serveCoffee() {
System.out.println(coffeeMaker.makeCoffee());
}
}
Inyección por setter
Útil si las dependencias pueden cambiar en runtime (poco común, pero puede pasar).
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class Barista {
private CoffeeMaker coffeeMaker;
@Autowired
public void setCoffeeMaker(CoffeeMaker coffeeMaker) {
this.coffeeMaker = coffeeMaker;
}
public void serveCoffee() {
System.out.println(coffeeMaker.makeCoffee());
}
}
Consejo: si la dependencia es obligatoria, usa el constructor. Si no lo es — usa el setter.
3. Anotación @Bean — crear beans personalizados
La anotación @Bean se usa para indicar explícitamente a Spring que un método dentro de una clase de configuración crea un bean. Este enfoque es útil cuando no puedes o no quieres modificar la clase original (por ejemplo, si viene de una librería externa).
Ejemplo de uso de @Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
// Indicamos que esta clase es una configuración Java
@Configuration
public class CoffeeConfig {
// Este método crea el objeto CoffeeMaker
@Bean
public CoffeeMaker coffeeMaker() {
return new CoffeeMaker();
}
}
Ahora, en lugar de @Component, hemos declarado explícitamente que la clase CoffeeMaker se crea mediante el método coffeeMaker. Spring igualmente lo añadirá al contenedor IoC.
4. Uso práctico de todas las anotaciones
Ahora juntemos todo en una pequeña aplicación.
Clase 1: CoffeeMaker
import org.springframework.stereotype.Component;
@Component
public class CoffeeMaker {
public String makeCoffee() {
return "☕ ¡Café listo!";
}
}
Clase 2: Barista
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
@Component
public class Barista {
private final CoffeeMaker coffeeMaker;
@Autowired
public Barista(CoffeeMaker coffeeMaker) {
this.coffeeMaker = coffeeMaker;
}
public void serveCoffee() {
System.out.println(coffeeMaker.makeCoffee());
}
}
Clase 3: CoffeeShopConfig (usando @Bean)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CoffeeShopConfig {
@Bean
public String coffeeRecipe() {
return "Receta de café: tomar café, añadir agua y amor!";
}
}
Clase principal para ejecutar
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
@SpringBootApplication
public class CoffeeShopApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(CoffeeShopApplication.class, args);
// Obtenemos Barista del contenedor IoC
Barista barista = context.getBean(Barista.class);
barista.serveCoffee();
// También está disponible el bean con la receta de café
String recipe = context.getBean(String.class);
System.out.println(recipe);
}
}
5. Errores típicos y cómo evitarlos
Falta del bean
Si no marcas la clase con @Component ni defines un método con @Bean, Spring no la añadirá al contenedor IoC. Al final obtendrás una NoSuchBeanDefinitionException.
Múltiples candidatos para @Autowired
Cuando Spring encuentra dos beans del mismo tipo, no sabe cuál usar. Aquí ayuda la anotación @Qualifier.
@Autowired
@Qualifier("specialCoffeeMaker")
private CoffeeMaker coffeeMaker;
Dependencias inaccesibles
Si intentas inyectar dependencias por campo, pero está declarado private y no hay ni constructor ni setter, Spring no podrá hacer DI. La solución es obvia: usa constructores o setters.
Ahora sabes cómo trabajar con las anotaciones @Component, @Autowired y @Bean. Estos conceptos forman la base para escribir aplicaciones flexibles y modulares en Spring Framework. Ahora toca practicar.
GO TO FULL VERSION