我在@Autowired
类构造函数下使用@Configuration
注释。
@Configuration
public class MyConfiguration {
private MyServiceA myServiceA;
private MyServiceB myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
}
作为Spring documentation sais,我能够声明是否需要带注释的依赖项。
如果我将构造函数下的@Autowired
注释标记为required=false
,我说要自动装配的两个服务不是必需的(作为Spring文档sais):
@Autowired(required = false)
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
来自Spring文档:
在多参数方法的情况下,'required'参数是 适用于所有论点。
如何单独为每个构造函数参数设置required
属性?是否有必要在每个字段下使用@Autowired
注释?
此致
答案 0 :(得分:37)
如果您正在使用Java 8和Spring Framework 4,则可以使用Optional
。
@Autowired
public MyConfiguration(Optional<MyServiceA> myServiceA, Optional<MyServiceB> myServiceB){
myServiceA.ifPresent(service->{this.myServiceA = service});
myServiceB.ifPresent(service->{this.myServiceB = service});
}
答案 1 :(得分:23)
明确方法
基本上,您有一个bean,它具有一些必需和可选的依赖项。处理此场景的推荐方法,不仅是配置bean,还包括任何其他配置bean,只是为强制依赖创建一个构造函数,并使用setter注入可选的。
public class MyConfiguration {
private final MyServiceA myServiceA;
private MyServiceB myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
}
@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = myServiceB;
}
}
使用这种方法,您可以轻松地对类进行单元测试,而无需任何模拟库。您可以使用构造函数和可选的setter创建处于测试状态的对象。
将@Autowired(required = false)
直接放在字段上并删除setter也可以,但由于您使用的是构造函数注入,我假设您希望更明确地声明依赖项。
其他想法
您还可以考虑使用Optional类型来包装非强制依赖项。开发人员通常认为,如果某个类具有属性,则应该设置它,这在您的方案中显然是不正确的。为了更清楚地标记特定依赖关系缺席的可能性,您可以使用Optional:
public class MyConfiguration {
private final MyServiceA myServiceA;
private Optional<MyServiceB> myServiceB
@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
this.myServiceB = Optional.empty();
}
@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = Optional.ofNullable(myServiceB);
}
}
有些人反对在类属性中使用Optional
类型(主要是因为这个answer from Brian Goetz),但最终它应该是整个团队做出的决定从事该项目。
答案 2 :(得分:8)
从Spring 4.3.0.RC1开始,你可以这样做:
public MyConfiguration(MyServiceA myServiceA, @Autowired(required = false) MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
添加ElementType.PARAMETER
作为注释目标。
从Spring 5.0 @Autowired(required = false)
也可以替换为@Nullable
,或者可以使用Kotlin可空类型而无需任何注释,例如MyServiceB?
答案 3 :(得分:1)
从Spring Framework 5.0开始,您还可以使用@Nullable注释(在任何包中都可以使用任何注释),例如,JSR-305中的javax.annotation.Nullable:
@Configuration
public class MyConfiguration {
private MyServiceA myServiceA;
private MyServiceB myServiceB
@Autowired
public MyConfiguration(@Nullable MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
}