构造函数参数解析

Bea*_*ast 3 java spring

我最近开始在3.2版本上工作.我试图理解构造函数参数解析,以防何时通过构造函数注入传递依赖项.我创建了以下示例.

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

请查看下面我使用的spring配置文件的实例.

<?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>
Run Code Online (Sandbox Code Playgroud)

在上面的场景中,调用的构造函数是第一个构造函数.但之后我稍微更改了xml文件并为两个参数添加了type属性.

<?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>
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,spring调用的构造函数是第二个构造函数.我不明白为什么spring决定调用第二个构造函数而不是第一个构造函数?在上面的例子中,当我们传递type属性时spring如何决定调用哪个构造函数?

Sot*_*lis 6

Spring使用一个ConstructorResolver实例来解析用于实例化类的构造函数.它调用autowireConstructor()方法来确定.您可以在线找到源代码.一个旧的版本,在这里.如果您有源(使用maven),您可以自己调试并完成它.

在该方法中,它尝试使用方法确定指定参数与控制器中的参数之间的差异ArgumentsHolder#getTypeDifferenceWeight().在我们的例子中,它将返回一个值,0因为参数匹配(即使是以不同的顺序).

将该minTypeDiffWeight值与值(最初Integer.MAX_VALUE)进行比较.如果它更小,则正在评估的当前构造函数将获得优先级并且值将替换minTypeDiffWeight.这个方法继续通过所有Class'构造函数,再次比较minTypeDiffWeight.由于两个构造函数都将给出0(0不小于0)的值,因此使用找到的第一个值.

正好

Juggler.class.getDeclaredConstructors();
Run Code Online (Sandbox Code Playgroud)

返回一个类似的数组

[public Test.Juggler(int,java.lang.String), public Test.Juggler(java.lang.String,int), public Test.Juggler()]
Run Code Online (Sandbox Code Playgroud)

其中第二个(声明的)构造函数首先出现.该getDeclaredConstructors()方法的javadoc状态

返回的数组中的元素没有排序,也没有任何特定的顺序.

所以这只是巧合.因为参数类型匹配,所以Spring选择它在该数组中找到的第一个构造函数.