web-dev-qa-db-ja.com

Spring Dataリポジトリは実際にどのように実装されていますか?

私はしばらくの間、私のプロジェクトでSpring Data JPAリポジトリを使用してきましたが、次の点を知っています。

  • リポジトリインターフェイスでは、findByCustomerNameAndPhone()などのメソッドを追加できます(customerNameおよびphoneがドメインオブジェクトのフィールドであると想定)。
  • 次に、Springは、実行時に(アプリケーションの実行中に)上記のリポジトリインターフェイスメソッドを実装することにより、実装を提供します。

私はこれがどのようにコーディングされているかに興味があり、Spring JPAのソースコードとAPIを見ましたが、以下の質問に対する答えを見つけることができませんでした:

  1. リポジトリ実装クラスは、実行時にどのように生成され、メソッドは実装および注入されますか?
  2. Spring Data JPAは、CGlibまたはバイトコード操作ライブラリを使用してメソッドを実装し、動的に注入しますか?

上記のクエリを支援し、サポートされているドキュメントを提供してください。

87
developer

まず第一に、進行中のコード生成はありません。つまり、CGLib、バイトコード生成はまったくありません。基本的なアプローチは、SpringのProxyFactory APIを使用してプログラムでJDKプロキシインスタンスを作成し、MethodInterceptorがインスタンスへのすべての呼び出しをインターセプトし、メソッドを適切な場所にルーティングすることです。

  1. リポジトリがカスタム実装部分で初期化されている場合(詳細については 参照ドキュメントのその部分 を参照)、呼び出されたメソッドはそのクラスに実装されている、コールはそこにルーティングされます。
  2. メソッドがクエリメソッドである場合(その決定方法については DefaultRepositoryInformation を参照)、ストア固有のクエリ実行メカニズムが起動し、決定されたクエリを実行します起動時にそのメソッドに対して実行されます。そのため、さまざまな場所で明示的に宣言されたクエリ(メソッドで@Queryを使用、JPA名前付きクエリを使用)を最終的にメソッド名からのクエリ派生にフォールバックする解決メカニズムが用意されています。クエリメカニズムの検出については、 JpaQueryLookupStrategy を参照してください。クエリ派生の解析ロジックは、 PartTree にあります。実際のクエリへのストア固有の翻訳は、たとえばin JpaQueryCreator .
  3. 上記のいずれにも当てはまらない場合、実行されるメソッドは、ストア固有のリポジ​​トリベースクラス(JPAの場合は SimpleJpaRepository )によって実装されるメソッドである必要があります。そのインスタンスにルーティングされます。

そのルーティングロジックを実装するメソッドインターセプターはQueryExecutorMethodInterceptorであり、高レベルのルーティングロジックは here にあります。

これらのプロキシの作成は、標準のJavaベースのFactoryパターン実装にカプセル化されます。高レベルのプロキシ作成は RepositoryFactorySupport にあります。次に、ストア固有の実装により必要なインフラストラクチャコンポーネントが追加されるため、JPAの場合は次のようなコードを記述できます。

EntityManager em = … // obtain an EntityManager
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);

私が明示的に言及する理由は、そのコードの中で、最初に実行するためにSpringコンテナを必要とするコードはないことを明確にする必要があるからです。クラスパス上のライブラリとしてSpringが必要です(ホイールを再発明しない方が望ましいため)が、一般的にはコンテナに依存しません。

DIコンテナーとの統合を容易にするために、もちろんXMLネームスペースであるSpring Java構成との統合を構築しましたが、 CDI拡張機能 。これにより、Spring Dataを単純なCDIシナリオで使用できます。

113
Oliver Drotbohm