【问题标题】:What is the logic in spring to choose constructor when ambiguity constructors prasents当歧义构造函数出现时,春天选择构造函数的逻辑是什么
【发布时间】:2015-12-03 20:26:43
【问题描述】:

首先我需要告诉我知道如何使用 Spring 配置文件中的类型和索引来解决这个问题。但我想了解当存在歧义构造函数时,spring 如何选择构造函数。

Pojo 类

package a.b.c;

public class Square {

    private String color;
    private int sideLength;

    public Square(String color, int sideLength) {
        System.out.println("Constructor id #1");
        this.sideLength = sideLength;
        this.color = color;
    }

    public Square(int sideLength, String color) {
        System.out.println("Constructor id #2");
        this.sideLength = sideLength;
        this.color = color;
    }

    public Square(Integer sideLength, String color) {
        System.out.println("Constructor id #3");
        this.sideLength = sideLength;
        this.color = color;
    }

    public void draw() {
        System.out.println("square color : " + color + ", sideLenth : " + sideLength);
    }

}

ApplicationContext.xml

<?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-2.5.xsd">

    <bean id="square" class="a.b.c.Square">
        <constructor-arg type="java.lang.String" value="red" />
        <constructor-arg type="int" value="10" />
    </bean>
</beans>

调用类

package a.b.c;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Application {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");

        Square square = (Square) context.getBean("square");
        square.draw();

    }

}

通过这种安排,它选择 #2 构造函数。

如果交换构造函数在源文件中的位置如下,则无需任何配置更改

package a.b.c;

public class Square {

    private String color;
    private int sideLength;

    public Square(int sideLength, String color) {
        System.out.println("Constructor id #2");
        this.sideLength = sideLength;
        this.color = color;
    }

    public Square(String color, int sideLength) {
        System.out.println("Constructor id #1");
        this.sideLength = sideLength;
        this.color = color;
    }

    public Square(Integer sideLength, String color) {
        System.out.println("Constructor id #3");
        this.sideLength = sideLength;
        this.color = color;
    }

    public void draw() {
        System.out.println("square color : " + color + ", sideLenth : " + sideLength);
    }

}

除了方法位置没有任何变化。 现在它选择 #1 构造函数。

我的问题是当出现歧义时选择构造函数的逻辑是什么。

注意:我知道这可以使用 index.html 解决。

【问题讨论】:

  • 你通过documentation了吗?
  • @Sotirios Delimanolis 感谢您提供此链接。是的,在发布之前,我确实浏览了这些以及大量的博客和技术文章。所有这些都说如何解决这个问题。但没有人说它是如何选择的。我的意思是选择构造函数在源中更改时如何更改。
  • 你的意思是当它交换源文件中的方法时执行构造函数得到改变?
  • 是的。它总是选择中间的 3 个
  • 谁能指出我在 github 中的源文件。所以我能理解..

标签: spring


【解决方案1】:

我认为您正在寻找它在代码级别的选择方式。但我不知道你为什么担心它。但个人感谢您为实现这一目标所做的努力,而不是随意相信。 我不确定我能否给出您想要的确切答案。但我会指导你。 spring 源代码在 github 中。这样你就可以检查自己了。

当它没有引导(使用索引)时,多个构造函数会混淆选择什么。它不能是随机的。正如你所说,它必须有逻辑。这就是它的工作原理。

spring 有类调用 ConstructorResolver。当 spring 需要解析构造函数时,它会去那里。在您的情况下,有 3 个构造函数符合条件。所有人都具有相同的资格。因为所有都是非引导的,所以它进入自动装配模式来解析候选构造函数。

所以它首先使用 java.util.comarator 对所有 3 个构造函数进行排序。之后它试图解析你所有的 3 个连接器。 (createArgumentArray) 但 Integer 构造函数会根据您给定的值生成异常。消失了,只剩下2个。 然后计算类型差异权重来选择方法。 (我认为我不应该在这里解释这个逻辑)它尝试对转换后的参数和原始参数进行类型差异权重。如果原始重量更好,那将是候选人。

我希望我已经给出了预期的答案。你可以从这里开始。如果还有什么不清楚的,请在下面评论。

编辑:sortConstructors 考虑更喜欢公共构造函数和具有最大参数数量的构造函数。结果将首先包含公共构造函数,参数数量减少,然后是非公共构造函数,参数数量再次减少。但在上述情况下排序不会生效。这就是在源更改时更改执行方法的原因。

【讨论】:

  • 是的..这就是我要找的。解释得很好。
【解决方案2】:

Spring利用这三个因素来选择构造函数

  1. 匹配参数的数量或数量。
  2. 匹配类型。
  3. 匹配订单。

您可以查看这篇解释歧义及其解决方法的文章。

http://www.bullraider.com/java/spring3/tutorials/spring-ioc-tutorials/resolving-ambiguity

【讨论】:

  • 我已经阅读了这篇文章。在我的情况下,参数数量是固定的。首先它选择了 (int sideLength, String color) 构造函数,然后选择了它的 (String color, int sideLength) 构造函数。我所做的唯一更改是更改该方法在源文件中的位置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多