El contenedor de Inversión de Control (IoC) de Spring es el núcleo del framework, responsable de instanciar, configurar y ensamblar los objetos conocidos como beans. Aunque las anotaciones son muy comunes hoy en día, la configuración basada en XML sigue siendo fundamental para entender los conceptos básicos de la inyección de dependencias.
Para ilustrar este proceso, diseñaremos un sistema de audio donde un equipo de sonido depende de un altavoz para reproducir sonido. Primero, definimos el contrato que cualquier altavoz debe cumplir:
package com.example.audio.system;
public interface Speaker {
void powerOn();
void playSound(String audioTrack);
}
A continuación, creamos una implementación concreta de esta interfaz para un altavoz Bluetooth:
package com.example.audio.system;
public class BluetoothSpeaker implements Speaker {
@Override
public void powerOn() {
System.out.println("Altavoz Bluetooth encendido y emparejado.");
}
@Override
public void playSound(String audioTrack) {
System.out.println("Reproduciendo audio por Bluetooth: " + audioTrack);
}
}
Lueego, definimos la clase principal AudioSystem. Esta clase posee propiedades básicas como marca y modelo, además de una dependencia hacia la interfaz Speaker. La inyección se realizará a través de métodos setter.
package com.example.audio.system;
public class AudioSystem {
private String brand;
private String model;
private Speaker speaker;
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public Speaker getSpeaker() {
return speaker;
}
public void setSpeaker(Speaker speaker) {
this.speaker = speaker;
}
public void startPlayback(String track) {
speaker.powerOn();
speaker.playSound(track);
}
}
Con las clases Java definidas, procedemos a configurar el archivo XML (por ejemplo, audio-config.xml). En este archivo se declaran los beans, se asignan identificadores únicos y se establecen las relaciones entre ellos.
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- Definición del bean para el altavoz -->
<bean id="btSpeaker" class="com.example.audio.system.BluetoothSpeaker"/>
<!-- Definición del bean para el sistema de audio -->
<bean id="mainAudioSystem" class="com.example.audio.system.AudioSystem">
<property name="brand" value="Sony" />
<property name="model" value="X-Series" />
<!-- Inyección de dependencia por referencia -->
<property name="speaker" ref="btSpeaker" />
</bean>
</beans>
Las etiquetas y atributos clave en esta configuración son:
- id: Un identificador único para referenciar el bean dentro del contenedor.
- class: La ruta completa (fully qualified name) de la clase que Spring debe instanciar.
- property: Permite inyectar valores en los atributos de la clase usando el método setter correspondiente. El atributo
nameindica el nombre de la propiedad en la clase Java. - value: Asigna un valor literal (como cadenas de texto o números) a una propiedad.
- ref: Establece una referencia a otro bean ya definido en el contexto, facilitando la inyección de dependencias entre objetos.
Para probar la configuración, utilizamos el contexto de la aplicación de Spring. La interfaz ApplicationContext y su implementación ClassPathXmlApplicationContext permiten cargar el archivo XML y obtener las instancias gestionadas por el framwork.
package com.example.audio.system;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AudioApp {
public static void main(String[] args) {
// Carga del contexto desde el archivo XML en el classpath
ApplicationContext context = new ClassPathXmlApplicationContext("audio-config.xml");
// Recuperación del bean por su identificador
AudioSystem system = (AudioSystem) context.getBean("mainAudioSystem");
// Ejecución de la lógica de negocio
system.startPlayback("Mi Canción Favorita");
// Verificación de las propiedades inyectadas
System.out.println("Marca del equipo: " + system.getBrand());
System.out.println("Modelo del equipo: " + system.getModel());
}
}
Al ejecutar la clase AudioApp, el contenedor IoC lee el archivo XML, instancia BluetoothSpeaker, crea el objeto AudioSystem, inyecta los valores de texto y la referencia del altavoz, y finalmente devuelve el bean completamente ensamblado listo para su uso en el método main.