クラスのさまざまなフィールドに@Autowired
アノテーションを使用し、フィールドを設定できるセッターやコンストラクターを作成しなかったとします。
質問-アクセス修飾子は、private
またはpackage-private
(つまり、なし)とは何ですか?
例えば:
public class MyClass {
@Autowired
private MyService myService;
}
vs
public class MyClass {
@Autowired
MyService myService;
}
最初のケース(private
fields)の場合、Springは、セッターがない場合でも、反射を使用してフィールドを配線します。
2番目のケース(package-private
フィールド)では、テスト目的でクラスを拡張する必要がある場合に、これらのフィールドにアクセスできるようになります(たとえば、モックを設定するため)。
したがって、どちらの場合も正常に機能しますが、特にテストに関して、どちらがより推奨されますか?
最初のケースでは、フレームワークに応じてモックを注入することもできます。たとえば、Mockitoの@InjectMocks
アノテーションを使用します。 SpringテストではReflectionTestUtils.setField
もあります...
私は個人的にテスト目的でクラスをあまり変更するのが好きではないので、最初のケースに行きます。しかし、結局のところ、これはお好みのテストフレームワークに大きく依存します。
私は通常、フィールドをプライベートにし、セッターインジェクションを使用することを好みます。
public class MyClass {
private MyService myService;
@Autowired
public void setMyService(MyService myService) {
this.myService = myService;
}
}
サービスを@Autowiredにすることができますが、単体テスト用にモックされたインスタンスで設定されます。
したがって、どちらの場合も正常に機能しますが、特にテストに関して、どちらがより推奨されますか?
プロパティはprivate
である必要があると思います:
@Autowired
private MyService myService;
他のクラスがプロパティに直接アクセスできるようにするのではなく、プロパティへのアクセスを提供するgetterメソッドがあると常に便利です。
また、テストの目的で、private properties
のmocks
の注入は、package-private
プロパティの注入と同じように機能します。
たとえば、Mockito
を使用すると、次のようにprivate MyService
のモックをMyClass
に挿入できます。
public class MyClassTest {
@Mock
MyService service;
@InjectMocks
MyClass serv = new MyClass();
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
}
私は通常、プライベートフィールドやメソッドに@Autowiredを使用しません。 @Autowiredは、外部の誰かがこのフィールドを設定することを意味します。一方、「プライベート」とは、このクラス以外の誰もがそれを使用できないことを意味します。
JITコンパイラが何らかの方法でこのコードを最適化すると、@ Autowiredとprivateを混在させると理論的に問題が発生する可能性があります。 Javaメモリモデルの同時実行性に関連する問題である可能性があります。これは、本番環境でのみ発生し、再現できません。
Autowiredフィールドを少なくともパッケージが見えるようにします。無料のボーナスとして、トリックや回避策なしでユニットテストを書くことができます。
PDATE:さらに、Javaメモリモデル関連の可視性の競合を回避するために、volatile
などのフィールドを宣言します。Spring開発者は自動配線フィールドを機能させるためにいくつかのトリックを行いますアクセスを明示的に同期せずに、これらのトリックがどのハードウェアのどのJVMでもスムーズに機能するかどうかはわかりません。
いくつかの理由から、@ Autowiredフィールドでprivateを使用したいと思います。