web-dev-qa-db-ja.com

@Autowiredコンストラクターのパラメーターを「required = false」として個別に設定する方法

@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としてマークすると、自動配線される2つのサービスは不要であると言っています

@Autowired(required = false)
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
  this.myServiceA = myServiceA;
  this.myServiceB = myServiceB;   
}

Springドキュメントから:

複数の引数メソッドの場合、「必須」パラメーターはすべての引数に適用できます。

required属性を各コンストラクターパラメーターに個別に設定するにはどうすればよいですか?すべてのフィールドで@Autowired注釈を使用する必要がありますか?

よろしく、

33
jcgarcia

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});   
}
40
Strelok

明示的アプローチ

基本的に、いくつかの必須およびオプションの依存関係を持つBeanがあります。構成Beanだけでなく、このシナリオを処理するための推奨される方法は、必須の依存関係にのみコンストラクターを作成し、オプションの依存関係にセッターインジェクションを使用することです。

_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)をフィールドに直接配置し、セッターを削除することもできますが、コンストラクター注入を使用しているため、依存関係をより明示的に記述したいと思います。

追加のアイデア

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型を使用することに反対する人もいます(主にこのため Brian Goetzからの回答 )が、結局は全体によって決定されるべきですプロジェクトに取り組むチーム。

26

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 nullable型を使用することもできます。 _MyServiceB?_

10
Czar

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