I have a class named as PoeticJuggler which has two constructors as follows:
@Autowired(required=false)
public PoeticJuggler(Sonnet29 poem)
{
super();
this.poem=poem;
System.out.println("Test to all");
}
@Autowired(required=false)
public PoeticJuggler(TestConstJuggler tst)
{
super();
this.poem=new Sonnet29();
System.out.println("Test to Test Juggler");
}
public PoeticJuggler(int beanBags,Poem poem)
{
super(beanBags);
this.poem=poem;
}
And the configuration file is like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config />
<bean id="duke" class="com.springinaction.springidol.beans.Juggler">
<constructor-arg value="15"/>
</bean>
<bean id="sonnet29" class="com.springinaction.springidol.beans.Sonnet29">
</bean>
<bean id="testDuke" class="com.springinaction.springidol.beans.TestConstJuggler">
</bean>
<bean id="poeticDuke" class="com.springinaction.springidol.beans.PoeticJuggler">
</bean>
<bean id="theStage" class="com.springinaction.springidol.beans.Stage" factory-method="getInstance">
</bean>
</beans>
When i run the following code:
public class BeanContext
{
public static void main(String[] args) throws PerformanceException
{
ApplicationContext ctx=new ClassPathXmlApplicationContext("performancebean.xml");
Performer performer=(Performer)ctx.getBean("poeticDuke");
performer.perform();
}
}
i get the output as:
Test to Test Juggler JUGGLING 3 BEANBAGS
My confusion is that how spring is identifying which constructor to call, as both of the mentioned constructors are getting satisfied.
I tried to simulate the use case, to me it purely depends upon the order of constructors returns by the reflection when multiple constructors getting satisfied. try the below in the beanContext and let us know the order. Note** There is no grantee that reflection returns the order as its presents in code.
Constructor<MainClass>[] methods = <yourClass>.class.getConstructors();
for (int i = 0; i < methods.length; i++) {
Class<?>[] types = methods[i].getParameterTypes();
System.out.println("Constructor "+i);
for (int j = 0; j < types.length; j++) {
System.out.println("Param Type" + types[j].getName());
}
}
UPDATE: To understand more clearly find the sorting logic found in AutoWireUtils.sortConstructors . this method being called once the spring get all constructors using the below line
candidates = (mbd.isNonPublicAccessAllowed() ?
beanClass.getDeclaredConstructors() : beanClass.getConstructors());
AutoWireUtils.sortConstructors
public static void sortFactoryMethods(Method[] factoryMethods) {
Arrays.sort(factoryMethods, new Comparator<Method>() {
@Override
public int compare(Method fm1, Method fm2) {
boolean p1 = Modifier.isPublic(fm1.getModifiers());
boolean p2 = Modifier.isPublic(fm2.getModifiers());
if (p1 != p2) {
return (p1 ? -1 : 1);
}
int c1pl = fm1.getParameterTypes().length;
int c2pl = fm2.getParameterTypes().length;
return (new Integer(c1pl)).compareTo(c2pl) * -1;
}
});
}
So , it is purely based on Sort , in case both constructors has same weight then it is matter of how reflection returns the constructors.
In this situation Spring identifies the proper bean by constructor parameter type.
When Spring performs autowiring and finds that
@Autowired(required=false)
public PoeticJuggler(Sonnet29 poem) {
...
it reads its constructor parameter type com.springinaction.springidol.beans.Sonnet29
. Then it determines that there is only one bean with such a class in the context so it instantiates sonnet29
bean first then instantiates poeticDuke
passing reference to sonnect29
as concstuctor arg.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.