在 child 未实现所有构造函数时实例化基 class
Instantiate base class when child does not implement all constructors
考虑一个简单的 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
的子class,它使用所提供的两个构造函数之一。我的 class 层次结构现在变为:
@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 的作者等参数来创建子 class。
另请注意,如果我定义(无用的)A1(Integer)
和 A1(String)
构造函数,Spring 不会再抱怨了。
使用Spring 4.2.2.RELEASE.
为什么当我定义了一些 child 时,bean factory 不能用它的构造函数创建基础 class 实例?
请找一个单元测试重现它in Github repo。
此行为的原因是:Spring不要使用构造函数参数来确定要实例化的适当 bean 类型。 (或者,换句话说:它只使用构造函数参数来解析要使用的正确构造函数)
我们只考虑这一行beanFactory.getBean(A.class, 1);
bean 解析如下:
确定所有请求类型的bean。在您的情况下:有 2 种可能的 bean:A 或 A1(均为 A 类型)
为第 1 步中找到的每种可能类型创建一个实例 ,并根据给定的参数 使用最合适的构造函数来实现。在您的情况下,使用带有 Integer 的构造函数实例化一个 A 和一个 A1。 (旁注:我们在这里谈论 prototype beans。对于 singleton beans :当且仅当它还没有创建新实例时存在)
在第 2 步的所有实例化 bean 中查找 @Primary(如果找到 return 它)
在步骤 2 的所有实例化 bean 中寻找优先级最高的 bean(如果找到 return 它)
扔一个"no unique bean exception"
在您的情况下:当尝试使用一个 Integer 参数实例化 A1 类型的 bean 时,算法在第 2 步失败。
当您定义 A1(String)
和 A1(Integer)
时:算法不会在第 2 步失败,因此转到第 3 步并解析类型,因为 class 上的 @Primary答.
Source code is here。仔细查看此处描述的算法的第 353 --> 366 行。
我只能猜测这种行为的原因,但这可能是因为您可以为构造函数参数指定默认值,因此:构造函数参数(传递给 getBean(Class, args...)
)不是消除 bean 歧义的有效线索类型。
考虑一个简单的 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
的子class,它使用所提供的两个构造函数之一。我的 class 层次结构现在变为:
@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 的作者等参数来创建子 class。
另请注意,如果我定义(无用的)A1(Integer)
和 A1(String)
构造函数,Spring 不会再抱怨了。
使用Spring 4.2.2.RELEASE.
为什么当我定义了一些 child 时,bean factory 不能用它的构造函数创建基础 class 实例?
请找一个单元测试重现它in Github repo。
此行为的原因是:Spring不要使用构造函数参数来确定要实例化的适当 bean 类型。 (或者,换句话说:它只使用构造函数参数来解析要使用的正确构造函数)
我们只考虑这一行beanFactory.getBean(A.class, 1);
bean 解析如下:
确定所有请求类型的bean。在您的情况下:有 2 种可能的 bean:A 或 A1(均为 A 类型)
为第 1 步中找到的每种可能类型创建一个实例 ,并根据给定的参数 使用最合适的构造函数来实现。在您的情况下,使用带有 Integer 的构造函数实例化一个 A 和一个 A1。 (旁注:我们在这里谈论 prototype beans。对于 singleton beans :当且仅当它还没有创建新实例时存在)
在第 2 步的所有实例化 bean 中查找 @Primary(如果找到 return 它)
在步骤 2 的所有实例化 bean 中寻找优先级最高的 bean(如果找到 return 它)
扔一个"no unique bean exception"
在您的情况下:当尝试使用一个 Integer 参数实例化 A1 类型的 bean 时,算法在第 2 步失败。
当您定义 A1(String)
和 A1(Integer)
时:算法不会在第 2 步失败,因此转到第 3 步并解析类型,因为 class 上的 @Primary答.
Source code is here。仔细查看此处描述的算法的第 353 --> 366 行。
我只能猜测这种行为的原因,但这可能是因为您可以为构造函数参数指定默认值,因此:构造函数参数(传递给 getBean(Class, args...)
)不是消除 bean 歧义的有效线索类型。