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


111

私のプロジェクトではSpring Data JPAリポジトリをしばらく使用しており、以下の点を知っています。

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

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

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

上記のクエリを支援し、サポートされているドキュメントを提供してもらえますか?

回答:


144

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

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

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

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

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

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

もちろん、DIコンテナーとの統合を容易にするために、Spring Java構成、XML名前空間だけでなくCDI拡張機能との統合も構築しました。これにより、Spring DataをプレーンなCDIシナリオで使用できます。


3
こんにちは、オリバー、@Repository最初にSpringが注釈付きインターフェースを発見する方法について詳しく説明していただけますか これを見るとRepositoryFactorySupport#getRepository()、インターフェイスクラスをパラメーターとして取るので、別の場所で発見する必要があります。私は特に、注釈付きインターフェースを見つけ、そのインターフェースを実装するJDKプロキシBeanを自動生成する方法を見つけようとしています。これは、Spring-Dataと非常によく似ていますが、リポジトリに関連しないアプリケーション固有の目的のためです。
クリス・ライス

1
あなたは見てみたいかもしれませんRepositoryComponentProvider。自動的に行われることはありませんが、コンポーネントは特定のタイプ(アノテーション付きまたはアノテーション付き)をスキャンしFactoryBean、それぞれに対して構成されます。
Oliver Drotbohm 2017年

2
古いスレッドについてコメントして申し訳ありませんが、興味がありました...リポジトリはシングルトンオブジェクトをプロキシしますか?コードがrepoメソッドを呼び出そうとしているという問題が発生していますが、プロキシで呼び出すことができないようです。ハングアップするだけです。忙しいシングルトンを待っているのかな。
iu.david
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.