Inversion of Control (IoC) es el principio por el que la responsabilidad de crear y gestionar objetos pasa de la propia aplicación al contenedor (Spring). En lugar de que un objeto cree sus dependencias, el contenedor las provee.
Dependency Injection (DI) es el mecanismo que implementa IoC: el contenedor inyecta las dependencias en el objeto.
// Sin IoC: el objeto gestiona su dependencia
public class UserService {
private UserRepository repo = new MySQLUserRepository(); // acoplado
}
// Con IoC: Spring inyecta la dependencia
@Service
public class UserService {
private final UserRepository repo; // desacoplado — interfaz
public UserService(UserRepository repo) { this.repo = repo; }
}Tipos de Inyección de Dependencias:
| Tipo | Cuándo usar | Anotación |
|---|---|---|
| Constructor | Siempre que sea posible (recomendado) | @Autowired (opcional si un constructor) |
| Setter | Dependencias opcionales | @Autowired en setter |
| Campo | Evitar (oculta dependencias, dificulta tests) | @Autowired en campo |
¿Por qué preferir inyección por constructor?
- Las dependencias son explícitas e inmutables (
final). - Facilita los tests: se puede crear el objeto manualmente sin contenedor.
- Spring puede detectar dependencias circulares en compilación.
Anotaciones clave:
@Autowired // inyección automática por tipo
@Qualifier("miBean") // especifica qué bean inyectar si hay ambigüedad
@Primary // bean preferido cuando hay múltiples del mismo tipo
@Value("${app.nombre}") // inyecta valor de properties- Bajo acoplamiento: código de negocio depende de interfaces, no de implementaciones.
- Testabilidad: se puede inyectar mocks en los tests.
- Configuración centralizada: Spring gestiona el ciclo de vida.
- Menos boilerplate: no hay
new SomeService(new SomeRepo(new DataSource(...))).
Ver ExpIoC.java, ExpDependencyInjection.java, ExpQualifier.java, ExpBeanScopes.java y ExpEventPublisher.java para ejemplos ejecutables con IoC, inyección de dependencias y configuración del contenedor Spring.