Springを使用してアプリケーションを開発しています。@Service
アノテーションを使用する必要があります。私が持っているServiceI
とServiceImpl
、そのようなことServiceImpl implements ServiceI
。@Service
注釈をどこに保持するべきかについて、ここで混乱しています。
インターフェースまたは実装に注釈を付ける必要がありますか@Service
?これら2つのアプローチの違いは何ですか?
Springを使用してアプリケーションを開発しています。@Service
アノテーションを使用する必要があります。私が持っているServiceI
とServiceImpl
、そのようなことServiceImpl implements ServiceI
。@Service
注釈をどこに保持するべきかについて、ここで混乱しています。
インターフェースまたは実装に注釈を付ける必要がありますか@Service
?これら2つのアプローチの違いは何ですか?
回答:
インターフェースを使用しない@Component
(または@Service
、...)。インターフェースが役に立たなくなるためです。その理由を説明させてください。
クレーム1:インターフェースがある場合、そのインターフェースを注入ポイントタイプに使用します。
クレーム2:インターフェースの目的は、いくつかの実装によって実装できるコントラクトを定義することです。反対側には注入ポイントがあります(@Autowired
)。インターフェイスを1つだけ、それを実装するクラスを1つだけ持つことは(IMHO)役に立たず、YAGNIに違反します。
事実:あなたが置くとき:
@Component
(または@Service
、...)インターフェースで、次に、NoUniqueBeanDefinitionException
(または、環境、プロファイル、または修飾子を使用した非常に特別な構成設定があります...)
結論:インターフェイスで@Component
(または@Service
、...)を使用する場合、2つのクレインの少なくとも1つに違反する必要があります。したがって@Component
、インターフェイスレベルで配置することは(いくつかのまれなシナリオを除いて)役に立たないと思います。
Spring-Data-JPAリポジトリーのインターフェースはまったく異なるものです
@Transactional
は、Beanへのプロキシが使用される例の1つです。AOPは別のものです。
基本的には同様の注釈@Service、@Repository、@Componentなどが、それらはすべて同じ目的を果たします:
注釈ベースの構成とクラスパススキャンを使用する場合の自動検出。
私の経験から、私は常に@Service
インターフェースまたは抽象的なクラスのアノテーション@Component
と@Repository
それらの実装のようなアノテーションを使用しています。@Component
これらのクラスで使用しているアノテーションは、基本的な目的、単純なSpring Bean、その他何も提供しません。レイヤーで@Repository
使用している注釈。DAO
たとえば、データベースと通信する必要がある場合、トランザクションがある場合などです。
その@Service
ため、機能に応じて、およびその他のレイヤーでインターフェースに注釈を付けることをお勧めします。
@Serviceにアノテーションを付ける利点は、それがサービスであることのヒントを与えることです。デフォルトでこの注釈を継承する実装クラスがあるかどうかはわかりません。
反対に、Spring固有のアノテーションを使用して、インターフェースをSpringなどの特定のフレームワークに結合します。インターフェースは実装から切り離されているはずなので、フレームワーク固有のアノテーションやインターフェースのオブジェクト部分を使用することはお勧めしません。
Springの利点の1つは、サービス(またはその他)の実装を簡単に切り替えることができることです。そのためには、インターフェースに注釈を付け、次のように変数を宣言する必要があります。
@Autowired
private MyInterface myVariable;
ではなく:
@Autowired
private MyClassImplementationWhichImplementsMyInterface myVariable;
最初のケースと同様に、注入する実装を一意にしてからアクティブ化できます(インターフェイスを実装するクラスは1つだけです)。2番目のケースでは、すべてのコードをリファクタリングする必要があります(新しいクラスの実装には別の名前があります)。結果として、アノテーションはできるだけインターフェース上にある必要があります。さらに、JDKプロキシはこれに最適です。ランタイムタイプはCGlibプロキシとは異なり、事前にわかっているため、アプリケーションの起動時に作成およびインスタンス化されます。
@Service
実装に注釈を付けて、インターフェースを自動配線することができます。Springは、このインターフェースを実装するオブジェクトをチェックします。
私は@Service
あなたのクラスに入れますが、インターフェースの名前を注釈へのパラメータとして入れます例えば
interface ServiceOne {}
@Service("ServiceOne")
class ServiceOneImpl implements ServiceOne{}
そうすることで、すべてのメリットが得られ、インターフェースを注入できますが、クラスを取得できます
@Autowired
private ServiceOne serviceOne;
したがって、インターフェイスはSpringフレームワークに関連付けられておらず、クラスをいつでも変更でき、すべての注入ポイントを更新する必要はありません。
したがって、実装クラスを変更したい場合は、新しいクラスに注釈を付けて最初のクラスから削除するだけで済みますが、変更する必要があるのはそれだけです。クラスを注入すると、実装クラスを変更したいときに多くの作業が発生する可能性があります。
簡単に言えば:
@Serviceは、サービス層のステレオタイプアノテーションです。
@Repositoryはのためのステレオタイプ注釈で永続化層。
@Componentは、アプリケーションコンテキストにオブジェクトのインスタンスを作成するようにSpringに指示するために使用される汎用ステレオタイプアノテーションです。インスタンスには任意の名前を定義できます。デフォルトはキャメルケースのクラス名です。
春の豆を作るために使用できる5つの注釈があります。回答を以下に記載してください。
本当にインターフェースが必要ですか?サービスインターフェイスごとに1つの実装を作成する場合は、それを避け、クラスのみを使用してください。もちろん、RMIがない場合、またはインターフェースプロキシが必要な場合。
@Repository-daoレイヤークラスを挿入するために使用します。
@Service-サービス層クラスを注入するために使用します。サービス層でも、dbトランザクション管理に@Transactionalアノテーションを使用する必要がある場合があります。
@Controller-Spring BeanとしてインジェクトするJSF管理対象Beanなどのフロントエンドレイヤーコントローラーに使用します。
@RestController-スプリングレストコントローラに使用します。これにより、毎回@ResponseBodyおよび@RequestBodyアノテーションをレストメソッドに配置することを回避できます。
@Component-コントローラ、サービス、またはdaoクラスではないSpring Beanを注入する必要がある場合、他のケースで使用します