Inyección de dependencia basada en constructor
La DI basada en constructores se logra cuando el contenedor invoca un constructor de clase con varios argumentos, cada uno de los cuales representa una dependencia de la otra clase.
Ejemplo
El siguiente ejemplo muestra una clase TextEditor que solo puede inyectarse en dependencia con inyección de constructor.
Tengamos un IDE de Eclipse en funcionamiento y sigamos los siguientes pasos para crear una aplicación Spring:
Pasos | Descripción |
---|---|
1 | Cree un proyecto con un nombre SpringExample y cree un paquete com.tutorialspoint bajo elsrc carpeta en el proyecto creado. |
2 | Agregue las bibliotecas Spring requeridas usando la opción Agregar JAR externos como se explica en el capítulo Ejemplo de Spring Hello World . |
3 | Crear clases de Java TextEditor , corrector ortográfico y MainApp bajo la com.tutorialspoint paquete. |
4 | Cree el archivo de configuración de Beans Beans.xml bajo elsrc carpeta. |
5 | El paso final es crear el contenido de todos los archivos Java y el archivo de configuración de Bean y ejecutar la aplicación como se explica a continuación. |
Aquí está el contenido de TextEditor.java archivo -
package com.tutorialspoint;
public class TextEditor {
private SpellChecker spellChecker;
public TextEditor(SpellChecker spellChecker) {
System.out.println("Inside TextEditor constructor." );
this.spellChecker = spellChecker;
}
public void spellCheck() {
spellChecker.checkSpelling();
}
}
A continuación se muestra el contenido de otro archivo de clase dependiente SpellChecker.java
package com.tutorialspoint;
public class SpellChecker {
public SpellChecker(){
System.out.println("Inside SpellChecker constructor." );
}
public void checkSpelling() {
System.out.println("Inside checkSpelling." );
}
}
A continuación se muestra el contenido de la MainApp.java archivo
package com.tutorialspoint;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
TextEditor te = (TextEditor) context.getBean("textEditor");
te.spellCheck();
}
}
A continuación se muestra el archivo de configuración Beans.xml que tiene configuración para la inyección basada en constructor -
<?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-3.0.xsd">
<!-- Definition for textEditor bean -->
<bean id = "textEditor" class = "com.tutorialspoint.TextEditor">
<constructor-arg ref = "spellChecker"/>
</bean>
<!-- Definition for spellChecker bean -->
<bean id = "spellChecker" class = "com.tutorialspoint.SpellChecker"></bean>
</beans>
Una vez que haya terminado de crear los archivos de configuración de fuente y bean, ejecutemos la aplicación. Si todo está bien con su aplicación, imprimirá el siguiente mensaje:
Inside SpellChecker constructor.
Inside TextEditor constructor.
Inside checkSpelling.
Resolución de argumentos de constructor
Puede haber una ambigüedad al pasar argumentos al constructor, en caso de que haya más de un parámetro. Para resolver esta ambigüedad, el orden en el que se definen los argumentos del constructor en una definición de bean es el orden en el que esos argumentos se suministran al constructor apropiado. Considere la siguiente clase:
package x.y;
public class Foo {
public Foo(Bar bar, Baz baz) {
// ...
}
}
La siguiente configuración funciona bien:
<beans>
<bean id = "foo" class = "x.y.Foo">
<constructor-arg ref = "bar"/>
<constructor-arg ref = "baz"/>
</bean>
<bean id = "bar" class = "x.y.Bar"/>
<bean id = "baz" class = "x.y.Baz"/>
</beans>
Veamos un caso más en el que pasamos diferentes tipos al constructor. Considere la siguiente clase:
package x.y;
public class Foo {
public Foo(int year, String name) {
// ...
}
}
El contenedor también puede usar la coincidencia de tipos con tipos simples, si especifica explícitamente el tipo del argumento del constructor usando el atributo de tipo. Por ejemplo
<beans>
<bean id = "exampleBean" class = "examples.ExampleBean">
<constructor-arg type = "int" value = "2001"/>
<constructor-arg type = "java.lang.String" value = "Zara"/>
</bean>
</beans>
Finalmente, la mejor manera de pasar argumentos de constructor es usar el atributo index para especificar explícitamente el índice de argumentos de constructor. Aquí, el índice se basa en 0. Por ejemplo
<beans>
<bean id = "exampleBean" class = "examples.ExampleBean">
<constructor-arg index = "0" value = "2001"/>
<constructor-arg index = "1" value = "Zara"/>
</bean>
</beans>
Una nota final, en caso de que esté pasando una referencia a un objeto, debe usar ref atributo de la etiqueta <constructor-arg> y si está pasando un valor directamente, debe usar value atributo como se muestra arriba.