java - 当子类未实现所有构造函数时实例化基类

标签 java spring inversion-of-control

考虑一个简单的 bean:

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class A {
    public A(Integer a){}
    public A(String a){}
}

拥有 BeanFactory 的实例我可以使用以下命令创建 A 实例:

beanFactory.getBean(A.class, 1); //  using A(Integer)
beanFactory.getBean(A.class, "1"); //  using A(String)

现在,我想要一个 A 的子类,它使用提供的两个构造函数之一。我的类层次结构现在变成:

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Primary
public class A {
    public A(Integer a) {}
    public A(String a) {}
}

@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class A1 extends A {
    public A1() { super(1); }
}

我希望这些现在可以工作:

beanFactory.getBean(A.class, 1); // using A(Integer)
beanFactory.getBean(A.class, "1"); // using A(String)
beanFactory.getBean(A1.class); // using the A1()

但是,前两次调用失败并显示

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'A1' defined in file [...]: Could not resolve matching constructor 
(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)

请注意,我并没有尝试使用像 this question 的作者这样的参数创建子类。 .

另请注意,如果我定义(无用的)A1(Integer)A1(String) 构造函数,Spring 不会再提示。

使用 Spring 4.2.2.RELEASE。

为什么当我定义一些子项时,bean 工厂无法使用其构造函数创建基类实例?

请找到一个重现它的单元测试 in Github repo .

最佳答案

此行为的原因是:Spring 不使用构造函数参数来确定要实例化的适当 bean 类型。 (或者,换句话说:它只使用构造函数参数来解析要使用的正确构造函数)

我们只考虑这一行 beanFactory.getBean(A.class, 1);

bean 分辨率如下:

  1. 确定具有请求类型的所有 bean。在你的情况下:有2种可能的bean:A或A1(两者都是A类型)

  2. 为第 1 步中找到的每种可能类型创建一个实例,并根据给定参数使用最合适的构造函数。在您的情况下,使用带有整数的构造函数实例化一个 A 和一个 A1。 (旁注:我们在这里讨论的是原型(prototype)bean。对于单例bean:当且仅当它尚不存在时才会创建一个新实例)

  3. 在第 2 步中在所有实例化 bean 中查找 @Primary(如果找到则返回)

  4. 在步骤 2 中查找所有实例化 Bean 中优先级最高的 Bean(如果找到则返回)

  5. 抛出“无唯一 bean 异常”

在您的情况下:当尝试使用一个整数参数实例化 A1 类型的 bean 时,算法在第 2 步失败。

当您定义 A1(String)A1(Integer) 时:算法在步骤 2 中不会失败,因此会转到步骤 3 并解析类型,因为A 类上的 @Primary。

Source code is here 。仔细查看第 353 行 --> 366 行,了解此处描述的算法。


我只能猜测这种行为的原因,但这可能是因为您可以为构造函数参数指定默认值,因此:构造函数参数(传递给 getBean(Class, args...) )不是消除 Bean 类型歧义的有效线索。

关于java - 当子类未实现所有构造函数时实例化基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34565344/

相关文章:

java - 如何从 Maven 依赖项创建更新包,该包仅与上次构建相比发生变化

java - UserService NullPointerException Spring/Hibernate

java - Bean Validation 将 Object RequestParam 转换为 @RequestBody

inversion-of-control - 如何使用 autofac 进行自定义初始化

asp.net-mvc - PerRequestLifetimeManager 和 Task.Factory.StartNew - 使用 Unity 进行依赖注入(inject)

c# - 如何在没有默认无参数构造函数的情况下为单个 WCF 服务注入(inject)参数

java - 处理游戏: Gif images not respawning as intended

java - 我可以在 Java 中使用双键映射吗

JavaFX webview 全局 CSS 深色主题

java - 如何使用 Spring RestTemplate 发送 XML POST 请求?