我在 @Configuration
类构造函数下使用 @Autowired
注释。
@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 文档所述):
@Autowired(required = false)
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
来自 Spring 文档:
在多参数方法的情况下,“必需”参数适用于所有参数。
如何分别为每个构造函数参数设置 required
属性?是否需要在每个字段下使用 @Autowired
注释?
问候,
如果您使用的是 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});
}
显式方法
基本上,您有一个具有一些必需和可选依赖项的 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;
}
}
使用这种方法,您可以轻松地对类进行单元测试,而无需任何模拟库。您可以使用构造函数和可选设置器创建处于测试状态的对象。
将 @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),但归根结底,应该由整个项目团队做出决定。
从 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?
No qualifying bean of type 'java.util.Properties' available: expected at least 1 bean which qualifies as autowire candidate.
从 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;
}
}
Optional
,但感谢您的回答;)this.myServiceA = myServiceA.orElse(null)
比myServiceA.ifPresent(service->{this.myServiceA = service})
更容易观察。this.myServiceA = myServiceA.orElse(this.myServiceA);