如何将@Autowired构造函数参数单独设置为“required = false”

时间:2017-02-09 11:10:25

标签: spring spring-boot constructor autowired

我在@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注释?

此致

4 个答案:

答案 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;    
   }
}