
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.