【发布时间】:2020-03-03 15:27:28
【问题描述】:
我正在编写一个工厂类,它根据给定的参数将返回接口的各种实现:
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 的自动装配)。
谢谢
【问题讨论】:
-
这就是
@Configuration类和条件的用途。 -
您可以使用
List<MyType> types作为构造函数参数。然后我要做的是用Map<String, MyType> types和getType返回types.get(param) -
@chrylis-onstrike- 你能举个例子吗?
-
至于不变性,除了
final,你还可以使用java.util.Collections.unmodifiableList() -
@ChristopherSchneider 该列表会被 Spring 自动装配吗?
标签: java spring dependency-injection autowired