3.4 Multiple Parameter Constructor Injection

The previous constructor examples all expected a single parameter constructor. The following examples will show different ways to set a two parameter constructor. The same techniques can applied be applied to more than two parameters, but will not be covered in the examples.

Example 3.14. Multiple Parameter Constructor Injection

This example's Message class has two different constructors. One takes two Strings and the other takes a String and an int.

Excerpt from chapter03-multiple-param-constructors/src/main/java/org/springbyexample/springindepth/chapter03/multipleParamConstructors/Message.java
                
public Message(String message, String person) {
    this.message = message;
    this.person = person;
}

public Message(String message, int numberOfTimes) {
    this.message = message;
    this.numberOfTimes = numberOfTimes;
}
                
            

This excerpt is similar to the previous constructor examples, but there is a second constructor argument. When Spring looks for a constructor matching this bean definition, the two values will be used in the order they are specified in the XML and their type will default to String. In this case, Spring correctly chooses the constructor that takes two Strings.

Excerpt from chapter03-multiple-param-constructors/src/main/resources/applicationContext.xml
                
<bean id="twoParamConstructor"
      class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg value="Spring comes before summer." />
    <constructor-arg value="Joe" />
</bean>
                
            

Example 3.15. Multiple Parameter Constructor Injection with different Argument Types

The first bean definition fails because even though number of times field was what was intended to be set for the second constructor argument, what was actually set with the value of “2” was the person field. This is because Spring will default values to Strings. If there was only one constructor that took a String and an int, Spring would have tried to convert the second value to the correct type. In this case, the bean definition twoParamFailureConstructor would have succeeded.

The second bean definition sets the type attribute so Spring will correctly convert the value “2” to an int. Then it is able to correctly choose the appropriate constructor which will set the message and number of times fields. The type attribute can take a primitive value like int or boolean, and also a class name like java.lang.String. The default type conversion will handle basic primitives and classes from the java.lang package.

Note that in the third bean definition, the arguments are not in the correct order. But because the type is set correctly to int on the first argument, Spring matches the two arguments to the only constructor that can take these two types and changes their order.

Excerpt from chapter03-multiple-param-constructors/src/main/resources/applicationContext.xml
                
<bean id="twoParamFailureConstructor"
           class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg value="Spring comes before summer." />
    <constructor-arg value="2" />
</bean>

<bean id="twoParamTypeConstructor"
      class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg value="Spring comes before summer." />
    <constructor-arg type="int" value="2" />        
</bean>

<bean id="twoParamUnorderedTypeConstructor"
      class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg type="int" value="2" />
    <constructor-arg value="Spring comes before summer." />        
</bean>
                
            

Example 3.16. Multiple Parameter Constructor Injection with indexed Arguments

The first bean definition specifies two constructor values. The problem with this definition is that the arguments aren't in the correct order for them to be set correctly. The constructor takes the message first and the person second, but the arguments in the XML have the person first and the message second.

The second bean definition fixes this by setting the index attribute. The index attribute starts at zero just like an array. The first argument is set to “1” and the second to “0”. So, constructor arguments can be specified in any order, but it's obviously less confusing to try to keep them ordered properly in the XML.

Excerpt from chapter03-multiple-param-constructors/src/main/resources/applicationContext.xml
                
<bean id="twoParamUnorderedFailureConstructor"
      class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg value="Joe" />
    <constructor-arg value="Spring comes before summer." />
</bean>

<bean id="twoParamIndexConstructor"
      class="org.springbyexample.springindepth.chapter03.multipleParamConstructors.Message">
    <constructor-arg index="1" value="Joe" />
    <constructor-arg index="0" value="Spring comes before summer." />
</bean>