ChatGPT解决这个技术问题 Extra ChatGPT

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

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

问候,

您应该使用: - 强制依赖项的构造函数注入 - 可选依赖项的 Setters 注入

S
Strelok

如果您使用的是 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});   
}

@AndrewTobilko 如果他正在考虑“可选”依赖项,那么 OP 肯定会检查空值。您也可以只有可选字段。许多方法可以确保您不会获得 NPE。
我不喜欢使用 Optional,但感谢您的回答;)
可选是前进的方向,IMO。可以很容易地从构造函数中查看依赖项是什么以及哪些是可选的,而无需查看所有的 setter。我认为在构造函数主体中 this.myServiceA = myServiceA.orElse(null)myServiceA.ifPresent(service->{this.myServiceA = service}) 更容易观察。
或者:this.myServiceA = myServiceA.orElse(this.myServiceA);
这看起来是一件很完美的事情,但 Intellij 的想法给出了一个关于在方法参数中使用 Optional 的警告。
C
Community

显式方法

基本上,您有一个具有一些必需和可选依赖项的 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 文档所说:“任何给定 bean 类的只有一个构造函数(最多)可以带有此注释,指示构造函数在用作 Spring bean 时自动装配”
请注意,示例中只有一个构造函数。第二个注释在 setter 方法上。您可以根据需要注释任意数量的 setter。
我的错,我没有将第二种方法视为二传手。当然,我知道我可以注释尽可能多的设置器和尽可能多的属性......但这是我想要避免的!
恕我直言,这是一种非常清晰和好的方法,应该是“要走的”。
C
Czar

从 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?


我完全像那样使用它,但与 @Qualifier 一起使用,仍然得到 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;    
   }
}