java - Autowire 通用型 Spring 4.1.7

标签 java spring generics autowired

<分区>

我正在使用大于 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 中。它无法在 AppleOrange 这两个 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());
}

关于java - Autowire 通用型 Spring 4.1.7,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32533145/

相关文章:

java - 使用 -Djavax.net.debug=all 调试 Java SSL 握手

java - 在 Spring.message 属性中添加新行时出错

java对象层次结构,并将对象传递给函数

Java通用二进制搜索树类型问题

java - 静态方法的泛型

java - Java 中冒泡排序的 Null Ptr 异常

java - 需要一个定时的 panel.repaint();

Java 媒体框架和 netBeans

java - 使用 Spring 的 @Value 注释插入时如何避免截断零前导数字?

javascript - 如何使用 ajax 和 spring MVC 填充模态表单