繁体   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