Constructor-based DI is performed by the container calling a constructor with a number of arguments, each of which represents a dependency. Calling a static factory method with specific arguments to create a bean is almost equivalent, and this analysis treats constructor and static factory method arguments the same way. The following example shows a class whose dependency can only be injected through the 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...
}

Please note that there is nothing special about this class. It is a POJO (plain Java object) that does not depend on specific container interfaces, base classes, or annotations.

Resolving constructor arguments

Constructor argument resolution mapping occurs using the argument type. If there is no potential ambiguity in the constructor arguments of a bean definition, then the order in which the constructor arguments are defined in the bean definition is the order in which those arguments are passed to the corresponding constructor when the bean is created. Consider the following class:

Java
package x.y;
public class ThingOne {
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}
Kotlin
package x.y
class ThingOne(thingTwo: ThingTwo, thingThree: ThingThree)

Assuming that the classes ThingTwo and ThingThree are not related by inheritance, there is no potential ambiguity. So the following configuration works fine and there is no need to explicitly specify indexes or types of constructor arguments in the <constructor-arg/> element.

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

If a reference is provided to another bean, then the type is known, so a mapping can occur (as happened in the previous example). If a simple type is used, such as <value>true</value>, Spring cannot determine the type of the value, and therefore cannot perform type matching without outside help. Consider the following class:

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
)
Constructor argument type mapping

In the previous scenario, the container can enable type mapping to simple types if the type of the constructor argument is explicitly specified using the type attribute, as shown in the following example:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>
Constructor argument index

You can use the index attribute to explicitly set the index of the constructor arguments, as shown in the following example:

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

In addition to disambiguating multiple prime values, specifying an index disambiguates if a constructor has two arguments of the same type.

The index is 0-based (starts at 0).
Constructor argument name

You can also use the constructor parameter name to resolve value conflicts, as shown in the following example:

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

Keep in mind that for this to work out of the box, the code must be compiled with the debug flag enabled so that Spring can look up the parameter name in the constructor. If you cannot or do not want to compile your code with the debug flag, then you can use the @ConstructorProperties JDK for explicitly naming your constructor arguments. Then the sample class should look like this:

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)