Constructor argument resolution
java, spring
Solution
Spring uses a `ConstructorResolver` instance to resolve which constructor to use to instantiate your class. It calls the `autowireConstructor()` method to determine that. You can find the source code online. An older version, here. If you have the source (use maven), you can debug and walk through it yourself.
Within the method it tries determine the difference between the specified arguments and the arguments in the controller with `ArgumentsHolder#getTypeDifferenceWeight()` method. In our case, it will return a value of `0` because the arguments match (even in a different order).
That value is compared to a `minTypeDiffWeight` value (originally `Integer.MAX_VALUE`). If it's smaller, the current constructor being evaluated gets priority and the value replaces `minTypeDiffWeight`. The method continues like this through all the Class' constructors, comparing again vs `minTypeDiffWeight`. Since both constructors will give a value of `0` (0 is not smaller than 0), the first one found is used.
It just so happens that
Juggler.class.getDeclaredConstructors();
returns an array like
[public Test.Juggler(int,java.lang.String), public Test.Juggler(java.lang.String,int), public Test.Juggler()]
where the second (declared) constructor appears first. The `getDeclaredConstructors()` method javadoc states
The elements in the array returned are not sorted and are not in any particular order.
So it's just coincidence. Because the argument types match, Spring chooses the first constructor it finds in that array.
Problem
I have recently started working on spring 3.2. I am trying to understand constructor argument resolution in case of when dependencies are passed through constructor injection. I have created the below example. ``` package com.springinaction.springidol; public interface Performer { void perform(); } package com.springinaction.springidol; public class Juggler implements Performer { private int beanBags=3; private String name; public Juggler(){ } public Juggler(String name,int beanBags){ System.out.println("First constructor gets called"); this.beanBags=beanBags; this.name=name; } public Juggler(int beanBags,String name){ System.out.println("Second constructor gets called"); this.beanBags=beanBags; this.name=name; } public void perform(){ System.out.println("JUGGLING "+beanBags+name+" BEANBAGS"); } } ``` Please find below instance of spring configuration file I have used. ``` <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="duke" class="com.springinaction.springidol.Juggler"> <constructor-arg value="Jinesh" /> <constructor-arg value="77" /> </bean> ``` In the above scenario the constructor invoked is the first constructor. But after that I slightly change the xml file and added the type attribute for both of the arguments. ``` <?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="duke" class="com.springinaction.springidol.Juggler"> <constructor-arg type="java.lang.String" value="Jinesh" /> <constructor-arg type="int" value="77" /> </bean> </beans> ``` In the above case the constructor invoked by spring is the second constructor. I don't understand why spring has decided to invoke the second constructor instead of the first one? In cases like above how spring decides which constructor to invoke when we pass the type attribute ?