web-dev-qa-db-ja.com

@Serviceアノテーションはどこに保存する必要がありますか?インターフェースまたは実装?

Springを使用してアプリケーションを開発しています。 @Serviceアノテーションを使用する必要があります。 ServiceImpl implements ServiceIのようなServiceIServiceImplがあります。ここで@Service注釈をどこに保持すべきかについて混乱しています。

インターフェイスまたは実装に@Serviceで注釈を付ける必要がありますか?これら2つのアプローチの違いは何ですか?

104
TheKojuEffect

@Component(または@Service、...)をインターフェイスに配置したことはありません。インターフェイスが役に立たなくなるからです。理由を説明します。

claim 1:インターフェイスがある場合は、そのインターフェイスを注入ポイントタイプに使用します。

claim 2:インターフェイスの目的は、複数の実装で実装できるコントラクトを定義することです。反対側には、注入ポイント(@Autowired)があります。インターフェースが1つだけで、それを実装するクラスが1つだけであると(IMHO)役に立たず、 YAGNI に違反します。

fact:置くとき:

  • インターフェイスで@Component(または@Service、...)、
  • それを実装する複数のクラスがあり、
  • 少なくとも2つのクラスがSpring Beanになります。
  • 型ベースの注入用のインターフェースを使用する注入ポイントがあります。

次にNoUniqueBeanDefinitionExceptionを取得します(または、環境、プロファイル、または修飾子を使用して、非常に特別な構成をセットアップします...)

結論:インターフェイスで@Component(または@Service、...)を使用する場合、少なくとも1つに違反する必要があります2つのクレーンの。したがって、@Componentをインターフェイスレベルに配置することは(いくつかのまれなシナリオを除き)役に立たないと思います。


Spring-Data-JPAリポジトリインターフェースは完全に異なるものです

111
Ralph

基本的に @ Service@ Repository@ Component などのアノテーションは、すべて同じ目的を果たします。

注釈ベースの構成およびクラスパススキャンを使用する場合の自動検出。

私の経験から、私は常に、インターフェースに@Serviceアノテーションを使用し、実装には@Component@Repositoryなどの抽象クラスとアノテーションを使用しています。 @Component注釈基本的な目的に役立つクラス、単純なSpring Beanで使用しているもの、それ以上は使用していません。 @Repositoryアノテーションは、DAOレイヤーで使用しています。データベースと通信する必要がある場合、トランザクションがある場合など。

したがって、@Serviceおよび機能に応じて他のレイヤーでインターフェイスに注釈を付けることをお勧めします。

33

@ Component、@ Service、@ Controller、@ Repositoryアノテーションは、実装クラスでのみ使用し、インターフェイスでは使用しませんでした。しかし、インターフェイスを使用した@Autowiredアノテーションは引き続き機能しました。

12
yalkris

@Serviceに注釈を付けることの長所は、それがサービスであるというヒントを与えることです。実装クラスがデフォルトでこの注釈を継承するかどうかはわかりません。

考慮すべき点は、スプリング固有の注釈を使用して、インターフェースを特定のフレームワーク、つまりスプリングと結合していることです。インターフェースは実装から切り離されることになっているため、フレームワーク固有の注釈やインターフェースのオブジェクト部分を使用することはお勧めしません。

7
Kuldeep Tiwari

Springの利点の1つは、サービス(またはその他の)実装を簡単に切り替えることです。そのためには、インターフェイスに注釈を付けて、次のように変数を宣言する必要があります。

@Autowired
private MyInterface myVariable;

ではなく:

@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;

最初のケースと同様に、一意である時点から注入する実装をアクティブ化できます(インターフェイスを実装するクラスは1つだけです)。 2番目のケースでは、すべてのコードをリファクタリングする必要があります(新しいクラスの実装には別の名前があります)。結果として、アノテーションは可能な限りインターフェース上にある必要があります。さらに、JDKプロキシはこれに非常に適しています。CGlibプロキシとは異なり、ランタイムタイプは事前にわかっているため、アプリケーションの起動時に作成およびインスタンス化されます。

1
François F.

簡単に言えば:

@ Serviceserviceレイヤーのステレオタイプ注釈です。

@ Repos­itorypersispertenceレイヤーのステレオタイプ注釈です。

@ Componentgenericステレオタイプアノテーションで、アプリケーションコンテキストでオブジェクトのインスタンスを作成するようSpringに指示するために使用されます。インスタンスに任意の名前を定義することができます。デフォルトはキャメルケースとしてのクラス名です。

0
HughParker