Pertama-tama, tidak ada pembuatan kode yang terjadi, yang berarti: tidak ada CGLib, tidak ada pembuatan kode byte sama sekali. Pendekatan dasarnya adalah bahwa instance proxy JDK dibuat secara terprogram menggunakan ProxyFactory
API Spring untuk mendukung antarmuka dan MethodInterceptor
memotong semua panggilan ke instance tersebut dan mengarahkan metode ke tempat yang sesuai:
- Jika repositori telah diinisialisasi dengan bagian implementasi kustom (lihat bagian dokumentasi referensi itu untuk detailnya), dan metode yang dipanggil diimplementasikan di kelas itu, panggilan akan diarahkan ke sana.
- Jika metode tersebut adalah metode kueri (lihat
DefaultRepositoryInformation
bagaimana itu ditentukan), mekanisme eksekusi kueri khusus penyimpanan akan menjalankan dan mengeksekusi kueri yang ditentukan untuk dieksekusi untuk metode itu saat memulai. Untuk itu mekanisme resolusi ada di tempat yang mencoba untuk mengidentifikasi kueri yang dideklarasikan secara eksplisit di berbagai tempat (menggunakan @Query
metode, JPA bernama kueri) yang akhirnya jatuh kembali ke derivasi kueri dari nama metode. Untuk deteksi mekanisme kueri, lihat JpaQueryLookupStrategy
. Logika parsing untuk derivasi kueri dapat ditemukan di PartTree
. Terjemahan khusus toko ke dalam kueri aktual dapat dilihat, misalnya di JpaQueryCreator
.
- Jika tidak ada di atas yang menerapkan metode yang dijalankan harus diterapkan oleh kelas basis repositori khusus toko (
SimpleJpaRepository
dalam kasus JPA) dan panggilan dialihkan ke instance dari itu.
Metode interceptor yang mengimplementasikan logika routing QueryExecutorMethodInterceptor
, logika routing tingkat tinggi dapat ditemukan di sini .
Pembuatan proxy tersebut dienkapsulasi menjadi implementasi pola Pabrik berbasis Java standar. Pembuatan proxy tingkat tinggi dapat ditemukan di RepositoryFactorySupport
. Implementasi khusus toko kemudian menambahkan komponen infrastruktur yang diperlukan sehingga untuk JPA Anda dapat melanjutkan dan cukup menulis kode seperti ini:
EntityManager em = … // obtain an EntityManager
JpaRepositoryFactory factory = new JpaRepositoryFactory(em);
UserRepository repository = factory.getRepository(UserRepository.class);
Alasan saya menyebutkannya secara eksplisit adalah bahwa itu harus menjadi jelas bahwa, pada intinya, tidak ada dari kode itu yang membutuhkan wadah Spring untuk berjalan di tempat pertama. Perlu Spring sebagai pustaka di classpath (karena kami lebih suka untuk tidak menemukan kembali roda), tetapi container agnostik secara umum.
Untuk memudahkan integrasi dengan kontainer DI, kami tentunya telah membangun integrasi dengan konfigurasi Spring Java, namespace XML, tetapi juga ekstensi CDI , sehingga Spring Data dapat digunakan dalam skenario CDI biasa.
@Repository
antarmuka beranotasi di tempat pertama? MelihatRepositoryFactorySupport#getRepository()
pertunjukan yang mengambil kelas antarmuka sebagai parameter, jadi itu harus ditemukan di tempat lain. Saya secara khusus mencoba mencari cara untuk menemukan antarmuka beranotasi dan secara otomatis menghasilkan kacang proxy JDK yang mengimplementasikan antarmuka, sangat mirip dengan data musim semi, tetapi untuk tujuan khusus aplikasi yang tidak terkait dengan Repositori.