我正在使用大于 4 的 Spring 版本。
我有使用@Configuration配置的具有相同父类(super class)的bean
@Configuration
public Class ConfigClass{
@Bean
public Apple apple(){stuff to return apple bean}
@Bean
public Orange orange(){stuff to return orange bean}
}
我有一个 bean,它可能由这两个 bean 中的任何一个组成
@Component
public Class FruitEater<ReturnType extends Fruit>{
@Bean
ReturnType fruit;
}
然后我收到了这条漂亮的歧义错误消息:
未定义 [fruit] 类型的合格 bean:预期单个匹配 bean 但找到 2: Autowiring 依赖项的 appleInjection、orangeInjection 失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException: Could not autowire field: fruiteater.bean;嵌套异常是 org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有定义 [fruit] 类型的合格 bean:预期单个匹配 bean 但找到 2:apple,orange
我的想法是,由于应该在编译时解析 ReturnType,因此 spring 应该能够基于通用类型 Autowiring 。我听说过 Spring 的 ResolvableType,但我不确定如何利用它,因为我对 Spring 还是很陌生。
有没有办法解决这个问题并使我的 FruitEater 成为通用的 FruitEater?
提前致谢。
您已经声明了一个单例(默认)FruitEater
bean。单例 bean 是 (YMMV) 急切初始化的。
在您的例子中,Spring 看到了 FruitEater
类型的 bean 定义,仅此而已。没有参数化(ReturnType
的参数),也没有提示应该将什么注入(inject)到 fruit
中。它无法在 Apple
和 Orange
这两个 bean 之间进行选择。
据推测,如果不是单例,您已经声明了具有原型(prototype)范围(或类似的东西)的 FruitEater
并且有像这样的注入(inject)目标
@Autowired
private FruitEater<Apple> fruitEater;
要注入(inject)的 bean 将在注入(inject)时创建,并且会有足够的类型信息来创建它并注入(inject)它的字段,即。本例中的 Apple
bean。
目前不支持。
一个解决方案是删除 FruitEater
bean 声明(@Component)
并提供适当的参数化子类型
@Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
@Autowired
protected ReturnType fruit;
}
Spring 现在足够聪明,利用 extends
子句中提供的类型信息,可以创建 OrangeEater
bean 并将 Orange
注入(inject)到它的 fruit
字段。
完整的例子
public class Sample {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigClass.class);
System.out.println(ctx.getBean(Injected.class).orangerEater);
System.out.println(ctx.getBean(Injected.class).appleEater);
}
@Component
static class Injected {
@Autowired
FruitEater<Orange> orangerEater;
@Autowired
FruitEater<Apple> appleEater;
}
}
@Configuration
@ComponentScan
class ConfigClass {
@Bean
public Apple apple() {
return new Apple();
}
@Bean
public Orange orange() {
return new Orange();
}
}
class Fruit {
}
class Apple extends Fruit {
}
class Orange extends Fruit {
}
@Component
class AppleEater extends FruitEater<Apple> {
}
@Component
class OrangeEater extends FruitEater<Orange> {
}
class FruitEater<ReturnType extends Fruit> {
@Autowired
protected ReturnType fruit;
}
或者,放弃组件扫描。使用构造函数注入(inject)。
public FruitEater(ReturnType fruit) {
this.fruit = fruit;
}
然后显式声明bean
@Bean
public FruitEater<Apple> appleEater() {
return new FruitEater(apple());
}