簡體   English   中英

Spring @Autowire 許多 bean

[英]Spring @Autowire many beans

我正在編寫一個工廠類,它根據給定的參數將返回接口的各種實現:

class Factory {
 public MyType getType(String param) {
  if (param.equals("A")) {
     return new MyTypeA();
   } else if (param.equals("B")) {
     return new MyTypeB();
 } 
}

現在我想利用 Spring 的依賴注入功能而不是new 我想使用基於@Annotation 的自動裝配。

首先想到的是在字段上使用@Autowire ,如下所示:

class Factory {
@Autowired
private MyTypeA myTypeA;
@Autowired
private MyTypeB myTypeB;
         public MyType getType(String param) {
          if (param.equals("A")) {
             return myTypeA;
           } else if (param.equals("B")) {
             return myTypeB;
         } 
        }

但是我記得不建議使用字段自動裝配,因為很難對此類類進行單元測試。

接下來我可以嘗試使用 setter 級別的自動裝配來進行測試:

class Factory {
private MyTypeA myTypeA;
private MyTypeB myTypeB;
         public MyType getType(String param) {
          if (param.equals("A")) {
             return myTypeA;
           } else if (param.equals("B")) {
             return myTypeB;
         } 

@Autowired
public void setMyTypeA(MyTypeA a) {
 this.myTypeA = a;
}

@Autowired
public void setMyTypeB(MyTypeB b) {
 this.myTypeB = b;
}
}

好的,這看起來更好,但是等等,還有更多 - 我希望我的類是不可變的,所以我希望我的私有字段是最終的,並且只在構造函數時填充。 所以接下來我可以嘗試的是基於構造函數的注入:

class Factory {

private final MyTypeA myTypeA;
private final MyTypeB myTypeB;

public Factory(MyTypeA myTypeA, MyTypeB myTypeB) {
 this.myTypeA = myTypeA;
 this.myTypeB = myTypeB;
}

         public MyType getType(String param) {
          if (param.equals("A")) {
             return myTypeA;
           } else if (param.equals("B")) {
             return myTypeB;
         } 
        }

看起來不錯,但問題來了——如果我有 20 種不同的類型,我可以根據參數值從這個工廠返回,我不能創建一個 20 參數的構造函數。

請建議,在這種情況下最好的方法是什么(試圖避免基於 xml 的自動裝配)。

謝謝

假設您所有的MyType類已經是 Spring 管理的 bean,您可以簡單地使用一個列表。

假設

@Configuration
class Config{
   @Bean
   public MyType myTypeA() {
      return new MyTypeA();
   }
   @Bean
   public MyType myTypeB() {
      return new MyTypeB();
   }
}

然后,您可以將 List 自動裝配到Factory

@Bean
public Factory factory(List<MyType> myTypes) {
   return new Factory(myTypes);
}

此列表將包含myTypeAmyTypeB 從那里,我可能會在Factory做這樣的事情:

public class Factory {

  final Map<String, MyType> myTypes;

  public Factory(List<MyType> types) {
     //build map of types with "param" as the key
  }

  public MyType getType(String param) {
     return myTypes.get(param);
  } 
}

您可以繼續遵循此方法。

    class Factory {
@Autowired
private MyTypeA myTypeA;
@Autowired
private MyTypeB myTypeB;
         public MyType getType(String param) {
          if (param.equals("A")) {
             return myTypeA;
           } else if (param.equals("B")) {
             return myTypeB;
         } 
        }

現在要解決在測試用例中注入模擬的問題,您只需使用 @InjectMocks 注釋即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM