2017-07-31 127 views
1

我有基類XY,其中有多個實現。但是,只有一個實現爲每個參數化類型,因此@Autowired應該能夠找出需要其子類。彈簧4依賴注入抽象泛型類不工作

在將第二個參數U添加到基類XY(從而添加到它們的所有子類)之前,這實際上起作用。但補充說,這裏是春天初始化過程中的錯誤後:

org.springframework.beans.factory.UnsatisfiedDependencyException: 錯誤創建名爲「對myApp」豆:不滿意依賴 通過實地「X1」表示;嵌套的例外是 org.springframework.beans.factory.UnsatisfiedDependencyException: 錯誤創建名爲「xImpl1」豆:不滿意依賴 通過現場表示「Y」;嵌套異常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:否 類型'test.Y>' 可用的符合條件的bean:預計至少有1個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僅知道抽象類Y,而不是它的實現類型(例如YImpl1)。

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

    protected T t; 
    protected V v; 

    // ... 

} 

一個POJO類:

public class A { 
    // pojo 
} 

一個簡單的界面:

public interface B { 
    // ... 
} 

這只是X的子類之一,但這是X與參數化類型的唯一子AB(即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> { 
    // ... 
} 

最後使用的實現:

@Component 
public class MyApp { 
    @Autowired 
    XImpl1 x1; // error 
} 

可能是有用的信息:

如果我做的類X和Y是非抽象,初始化錯誤消失,但後來連如果XImpl1覆蓋X上的一個方法,這在依賴注入之後不適用!即在MyApp中,調用x1.something()並不實際調用XImpl1的方法,而是調用X類的something()方法。

我可能在這裏犯了一些錯誤,如果有人能指出一些東西,我會很高興。但除此之外,似乎Spring仍然有一些限制?

回答

0

我不知道春天的限制。我建議簡化。別假設問題是春天:就是你。

我會說你的設計不必要的複雜。

我不能說這是一個例子還是你的真實代碼。您對泛型的命名和使用會導致無法閱讀和理解。你已經從這個類層次中抽象出所有的理解。

這聽起來像是一種情況,其中組合應該比繼承更受歡迎。這只是我的看法。

當您@Autowire構造函數,我建議在參數列表中添加一個@Qualifier與一個值,確切地說明您希望注入哪個bean。如果你有幾個相同類型的bean由你的bean工廠管理,那麼期望Spring會閱讀你的想法是不合理的。它不能選擇自動裝配哪一個。只有可以決定。

世界正朝着函數式編程的方向發展,遠離面向對象。我很想知道你是否可以通過使用lambdas和新的java.util.function包改善這一點。您可能會獲得更多靈活性和更好的理解。