我在Spring版本中工作时大于4。 我使用@Configuration配置了相同超类的bean
@Configuration
public Class ConfigClass{
@Bean
public Apple apple(){stuff to return apple bean}
@Bean
public Orange orange(){stuff to return orange bean}
}
我有一个可能由这两个豆子中的任何一个组成的豆子
@Component
public Class FruitEater<ReturnType extends Fruit>{
@Bean
ReturnType fruit;
}
我得到了这个美丽的歧义错误信息:
没有定义[fruit]类型的限定bean:期望的单个匹配bean但找到2:appleInjection,orangeInjection of autowired dependencies failed;嵌套异常是org.springframework.beans.factory.BeanCreationException:无法自动装配字段:fruiteater.bean;嵌套异常是org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有定义[fruit]类型的限定bean:期望的单个匹配bean但找到2:apple,orange
我的想法是,由于ReturnType应该在编译时解析,因此spring应该能够基于Generic Type进行Autowire。我听说过Spring的ResolvableType,但我不知道如何利用它,因为我还是Spring的新手。 有没有办法解决这个问题并让FruitEater成为通用的FruitEater?
提前谢谢。
答案 0 :(得分:1)
您已经声明了一个单例(默认)FruitEater
bean。单身豆是(YMMV)急切初始化。
在您的情况下,Spring会看到FruitEater
类型的bean定义,但就是这样。没有参数化(ReturnType
的参数),没有提示应该注入fruit
的内容。它无法在两个Apple
和Orange
bean之间进行选择。
据推测,如果您使用原型范围(或类似的东西)声明FruitEater
而不是单身,并且有注射目标,例如
@Autowired
private FruitEater<Apple> fruitEater;
要注入的bean将在注入时创建,并且将有足够的类型信息来创建它并注入其字段,即。这个例子中有一个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
字段中注入fruit
。 / p>
完整示例
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;
}
或者,抛弃组件扫描。使用构造函数注入。
public FruitEater(ReturnType fruit) {
this.fruit = fruit;
}
然后明确声明bean
@Bean
public FruitEater<Apple> appleEater() {
return new FruitEater(apple());
}