La DI basada en constructor la realiza el contenedor llamando a un constructor con una cantidad de argumentos, cada uno de los cuales representa una dependencia. Llamar a un método de fábrica static con argumentos específicos para crear un bean es casi equivalente, y este análisis trata los argumentos del constructor y del método de fábrica static de la misma manera. El siguiente ejemplo muestra una clase cuya dependencia sólo se puede inyectar a través del constructor:

Java

public class SimpleMovieLister {
    // SimpleMovieLister has a dependency on MovieFinder
    private final MovieFinder movieFinder;
    // constructor so that the Spring container can inject MovieFinder
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    // business logic that actually uses the embedded MovieFinder is omitted...
}
Kotlin

// constructor so that the Spring container can inject MovieFinder
class SimpleMovieLister(private val movieFinder: MovieFinder) {
    // business logic that actually uses the embedded MovieFinder is omitted...
}

Tenga en cuenta que esta clase no tiene nada de especial. Es un POJO (objeto Java simple) que no depende de interfaces de contenedor, clases base o anotaciones específicas.

Resolviendo argumentos del constructor

La asignación de resolución de argumentos del constructor se produce utilizando el tipo de argumento. Si no hay ambigüedad potencial en los argumentos del constructor de una definición de bean, entonces el orden en el que se definen los argumentos del constructor en la definición del bean es el orden en el que esos argumentos se pasan al constructor correspondiente cuando se crea el bean. Considere la siguiente clase:

Java
package x.y;
public class ThingOne {
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}
Kotlin
paquete x.y
clase CosaUno(cosaDos: CosaDos, cosaTres: CosaTres)

Suponiendo que las clases ThingTwo y ThingThree no están relacionadas por herencia, no hay ambigüedad potencial. Por lo tanto, la siguiente configuración funciona bien y no es necesario especificar explícitamente índices o tipos de argumentos del constructor en el elemento <constructor-arg/>.

<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </frijol>
    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>

Si se proporciona una referencia a otro bean, entonces se conoce el tipo, por lo que puede ocurrir un mapeo (como sucedió en el ejemplo anterior). Si se utiliza un tipo simple, como <value>true</value>, Spring no puede determinar el tipo del valor y, por lo tanto, no puede realizar la coincidencia de tipos sin ayuda externa. Considere la siguiente clase:

Java
package examples;
public class ExampleBean {
    // Number of years to calculate the final answer
    private final int years;
    // The answer to the main question of life, the universe and everything
    private final String ultimateAnswer;
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
Kotlin
package examples
class ExampleBean(
    private val years: Int, // Number of years to calculate the final answer
    private val ultimateAnswer: String // The answer to the main question of life, the universe and everything
)
Mapeo de tipos de argumentos del constructor

En el escenario anterior, el contenedor puede habilitar la asignación de tipos a tipos simples si el tipo del argumento del constructor se especifica explícitamente usando el atributo type, como se muestra en el siguiente ejemplo:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
Índice de argumentos del constructor

Puede utilizar el atributo index para establecer explícitamente el índice de los argumentos del constructor, como se muestra en el siguiente ejemplo:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

Además de eliminar la ambigüedad de varios valores primos, especificar un índice elimina la ambigüedad si un constructor tiene dos argumentos del mismo tipo.

El índice está basado en 0 (comienza en 0).
Nombre del argumento del constructor

También puede utilizar el nombre del parámetro del constructor para resolver conflictos de valores, como se muestra en el siguiente ejemplo:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg nombre="años" valor="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Tenga en cuenta que para que esto funcione de inmediato, el código debe compilarse con el indicador de depuración habilitado para que Spring pueda buscar el nombre del parámetro en el constructor. Si no puede o no quiere compilar su código con el indicador de depuración, puede usar annotation @ConstructorProperties JDK para nombrar explícitamente los argumentos de su constructor. Entonces la clase de muestra debería verse así:

Java
package examples;
public class ExampleBean {
    // Fields omitted
    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
Kotlin
package examples
class ExampleBean
@ConstructorProperties("years", "ultimateAnswer")
constructor(val years: Int, val ultimateAnswer: String)