抽象泛型类的Spring 4依赖注入不起作用

时间:2017-07-31 16:20:59

标签: java spring generics dependency-injection autowired

我有基类XY,它们有多个实现。但是,每个参数化类型只有一个实现,因此@Autowired应该能够确定需要哪个子类。

在将第二个参数U添加到基类XY(以及它们的所有子类)之前,这实际上是有效的。但是在添加之后,这是Spring初始化期间的错误:

  

org.springframework.beans.factory.UnsatisfiedDependencyException:   创建名为“myApp”的bean时出错:不满意的依赖项   通过字段'x1'表示;嵌套异常是   org.springframework.beans.factory.UnsatisfiedDependencyException:   创建名为“xImpl1”的bean时出错:不满意的依赖项   通过字段'y'表示;嵌套异常是   org.springframework.beans.factory.NoSuchBeanDefinitionException:没有   'test.Y>'类型的限定bean   可用:预计至少有1个符合autowire资格的bean   候选人。依赖注释:   {@ org.springframework.beans.factory.annotation.Autowired(所需=真)}

github(maven项目)中的代码:https://github.com/kevincentius/spring-di-abstract-generic-problem/tree/master/spring-test

抽象泛型类X<T, U>Y<T, U>互相引用:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public abstract class X<T, U> {

    protected T t;
    protected U u;

    @Autowired
    protected Y<T, X<T, U>> y; // error when initializing xImpl1

    // ...

}

班级Y知道实施班级V(例如XImpl1)。与仅知道抽象类X的{​​{1}}相反,而不是其实现类型(例如Y)。

YImpl1

pojo课程:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public abstract class Y<T, V extends X<T, ?>> {

    protected T t;
    protected V v;

    // ...

}

一个简单的界面:

public class A {
    // pojo
}

这只是public interface B { // ... } 的子类之一,但这是X的唯一子类,参数化类型为XA(即B的唯一子类{1}}):

X<A, B>

与上面相同 - @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class XImpl1 extends X<A, B> { // ... } 的唯一实现。虽然Y<A, B>的其他实现具有不同的参数化类型。

Y

最后使用实现:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class YImpl1 extends Y<A, XImpl1> {
    // ...
}

可能是有用的信息:

如果我将类X和Y设置为非抽象,则初始化错误消失,但即使XImpl1覆盖X上的方法,这也不适用于依赖注入之后!即在MyApp中,调用x1.something()实际上并不调用XImpl1的方法,而是调用X类的something()方法。

我可能在这里犯了一些错误,如果有人能指出一些问题,我会很高兴。但除此之外,看起来Spring仍然有一些局限性?

1 个答案:

答案 0 :(得分:0)

我不知道Spring的限制。我建议简化。停止假设问题是Spring:就是你。

我会说你的设计不必要地复杂。

我不知道这是一个例子还是你的真实代码。您对泛型的命名和使用使得无法阅读和理解。你已经从这个类层次结构中抽象出所有的理解。

这听起来像组合应优先于继承的情况。这只是我的意见。

当你@Autowire构造函数时,我建议在参数列表中添加一个@Qualifier,其值明确指出你要注入的bean。如果你有几个由bean工厂管理的相同类型的bean,那么期望Spring会读你的想法是不合理的。它无法选择哪一个自动装配。只有可以决定。

世界正朝着功能性编程的方向发展,远离面向对象。我很想知道您是否可以通过使用lambdas和新的java.util.function软件包来改进这一点。您可以获得更多的灵活性和更好的理解。