Spring constructor-arg multiple arguments

Spring constructor-arg multiple arguments

1. Overview

In this article, we will learn about the Spring constructor-arg multiple arguments.

1.1. Spring constructor injection

Dependency injection (DI) is a process whereby the Spring container gives the bean its instance variables. Here, The Spring container takes the responsibility of object creation and injecting its dependencies instead of the class creating the dependency objects by itself.

Let’s see an example to understand dependency injection.

Consider we provide the dependencies required by the class as arguments to the constructor. So each argument represents a dependency.

@Component
class Car @Autowired constructor (private val owner: Owner) {
    fun getOwner() : Owner {
        return owner
    }
}
class Owner(private val name: String, private val address: String) {}

Note that we have annotated the constructor using @Autowired. This annotation instructs the Spring framework to inject the owner dependency into the Car bean. However, as of Spring 4.3, you no longer need to add @Autowired annotation to the class that has only one constructor.

Since we have only one argument, there is no ambiguity, and the Spring framework resolves with no issues.

2. Spring constructor-arg multiple arguments injection

Constructor argument resolution happens using the argument’s type. We are using the XML configuration in this article for bean definition.

package com.tedblob
class Car(Owner owner, Dealer dealer)

For example, the above Owner and Dealer classes do not have any inheritance relationship, meaning they are not subclasses of any common superclass, so there is no ambiguity.

Therefore, the following bean configuration works fine, and you do not need to specify the constructor argument indexes or types explicitly in the <constructor-arg/> element. The <constructor-arg/> helps you to define the arguments of your constructor in the XML bean definition.

<beans>
    <bean id="car" class="com.tedblob.Car">
        <constructor-arg ref="owner"/>
        <constructor-arg ref="dealer"/>
    </bean>
    <bean id="owner" class="com.tedblob.Owner"/>
    <bean id="dealer" class="com.tedblob.Dealer"/>
</beans>

2.1. Spring constructor injection - argument type matching

Suppose you have a PurchaseStatus class with boolean and string primitive variables.

package com.tedblob
class PurchaseStatus(Boolean isPurchased, String nameOfBuyer) {
}

If you try to specify the below bean definition, it won’t work. Because Spring cannot determine the type of the value, meaning it cannot determine whether the value="true" belong to String or Boolean.

<bean id="purchaseStatus" class="com.tedblob.PurchaseStatus">
    <constructor-arg value="true"/>
    <constructor-arg value="JB"/>
</bean>

Therefore, you should explicitly specify the type of the constructor argument by using the type attribute as below:

<bean id="purchaseStatus" class="com.tedblob.PurchaseStatus">
    <constructor-arg type="Boolean" value="true"/>
    <constructor-arg type="java.lang.String" value="JB"/>
</bean>

Here, the Spring knows that the value="true" belongs to Boolean type and so resolves the constructor arguments accordingly.

2.2. Constructor injection - argument index

You can also use the index attribute alternatively to specify the index of constructor arguments:

<bean id="purchaseStatus" class="com.tedblob.PurchaseStatus">
    <constructor-arg index="0" value="true"/>
    <constructor-arg index="1" value="JB"/>
</bean>

In the above code, index 0 refers to the boolean first argument of the constructor, index 1 refers to the string second argument of the constructor.

Besides resolving the ambiguity of multiple simple values, specifying an index resolves ambiguity where a constructor has two arguments of the same type.

Consider the below class Bug that contains two string type desc and latestComment arguments in the constructor.

class Bug(String desc, String latestComment)

You can resolve the ambiguity of the same type by using the index as below:

<bean id="bug" class="com.tedblob.Bug">
    <constructor-arg index="0" value="Bug on UI home page"/>
    <constructor-arg index="1" value="In review by JB"/>
</bean>

2.3. Constructor injection - argument name

You can also use the constructor parameter name for value disambiguation using the name tag:

<bean id="bug" class="com.tedblob.Bug">
    <constructor-arg name="desc" value="Bug on UI home page"/>
    <constructor-arg name="latestComment" value="In review by JB"/>
</bean>

Note that this will work only if you enable debug flag in your app.

Alternatively, you can use the @ConstructorProperties JDK annotation to name your constructor arguments as below:

package com.tedblob
class Bug
@ConstructorProperties("desc", "latestComment")
constructor(val desc: String, val latestComment: String)

3. Conclusion

To sum up, we have learned about the Spring constructor-arg multiple arguments.

Leave a Reply

Your email address will not be published. Required fields are marked *