Spring Data havuzları gerçekte nasıl uygulanır?


111

Bir süredir projemde Spring Data JPA deposu ile çalışıyorum ve aşağıdaki noktaları biliyorum:

  • Depo arayüzlerinde, biz gibi yöntemleri ekleyebilirsiniz findByCustomerNameAndPhone()(varsayarak customerNameve phoneetki alanı nesne alanlardır).
  • Daha sonra Spring, yukarıdaki depo arayüzü yöntemlerini çalışma zamanında (uygulamanın çalıştırılması sırasında) uygulayarak uygulamayı sağlar.

Bunun nasıl kodlandığıyla ilgileniyorum ve Spring JPA kaynak koduna ve API'lerine baktım, ancak aşağıdaki sorulara cevap bulamadım:

  1. Çalışma zamanında ve yöntemler sırasında havuz uygulama sınıfı nasıl oluşturulur ve enjekte edilir?
  2. Spring Data JPA, yöntemleri uygulamak ve dinamik olarak enjekte etmek için CGlib veya herhangi bir bayt kodu işleme kitaplığı kullanıyor mu?

Lütfen yukarıdaki sorgulara yardımcı olabilir ve ayrıca desteklenen belgeleri sağlayabilir misiniz?

Yanıtlar:


144

Her şeyden önce, devam eden bir kod üretimi yok, bu da şu anlama geliyor: CGLib yok, bayt kodu üretimi yok. Temel yaklaşım, bir JDK proxy örneğinin, ProxyFactoryarabirimi desteklemek için Spring'in API'sini kullanarak programlı bir şekilde oluşturulması MethodInterceptorve örneğe yapılan tüm çağrıları kesip yöntemi uygun yerlere yönlendirmesidir:

  1. Depo özel bir uygulama bölümü ile başlatılmışsa ( ayrıntılar için referans belgelerinin o bölümüne bakın) ve çağrılan yöntem o sınıfta uygulanıyorsa, çağrı oraya yönlendirilir.
  2. Yöntem bir sorgu yöntemiyse ( DefaultRepositoryInformationbunun nasıl belirlendiğine bakın), depoya özgü sorgu yürütme mekanizması devreye girer ve başlangıçta bu yöntem için yürütüldüğü belirlenen sorguyu yürütür. Bunun için, çeşitli yerlerde açıkça bildirilmiş sorguları tanımlamaya çalışan ( @Queryyöntemde, JPA adlı sorgular kullanarak) sonunda yöntem adından sorgu türetmeye geri dönen bir çözüm mekanizması mevcuttur . Sorgu mekanizması tespiti için bkz JpaQueryLookupStrategy. Sorgu türetme için ayrıştırma mantığı şurada bulunabilir PartTree. Gerçek bir sorguya yapılan mağazaya özgü çeviri, örn JpaQueryCreator.
  3. Yukarıdakilerden hiçbiri uygulanmazsa, yürütülen yöntemin bir depoya özgü depo temel sınıfı ( SimpleJpaRepositoryJPA durumunda) tarafından uygulanmış olması gerekir ve çağrı, bunun bir örneğine yönlendirilir.

Yönlendirme mantığını uygulayan yöntem durdurucu QueryExecutorMethodInterceptor, yüksek seviyeli yönlendirme mantığı burada bulunabilir .

Bu proxy'lerin yaratılması, standart bir Java tabanlı Fabrika modeli uygulamasında kapsüllenmiştir. Üst düzey proxy oluşturma şurada bulunabilir RepositoryFactorySupport. Mağazaya özel uygulamalar daha sonra gerekli altyapı bileşenlerini ekler, böylece JPA için devam edebilir ve aşağıdaki gibi kod yazabilirsiniz:

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

Bundan açıkça bahsetmemin nedeni, özünde, bu kodun hiçbirinin ilk etapta bir Spring konteynırının çalışmasını gerektirmediğinin anlaşılması gerektiğidir. Spring'e sınıf yolunda bir kütüphane olarak ihtiyaç duyar (çünkü tekerleği yeniden icat etmemeyi tercih ederiz), ancak genel olarak konteyner agnostiktir.

DI kapsayıcılarıyla entegrasyonu kolaylaştırmak için, daha sonra elbette, bir XML ad alanı olan Spring Java yapılandırmasıyla ve aynı zamanda bir CDI uzantısı ile entegrasyon oluşturduk , böylece Spring Data düz CDI senaryolarında kullanılabilir.


3
Merhaba Oliver, @RepositorySpring'in ek açıklamalı arayüzleri ilk etapta nasıl keşfettiğini açıklayabilir misin? RepositoryFactorySupport#getRepository()Arayüz sınıfını bir parametre olarak aldığını göstermeye baktığımızda, başka bir yerde keşfedilmesi gerekir. Özellikle açıklamalı bir arabirimi nasıl bulacağımı ve otomatik olarak arabirimi uygulayan bir JDK proxy çekirdeğini nasıl oluşturacağımı anlamaya çalışıyorum, yay verilerine çok benzer, ancak Depolarla ilgili olmayan uygulamaya özel bir amaç için.
Chris Rice

1
Bir göz atmak isteyebilirsin RepositoryComponentProvider. Otomatik bir şey yoktur, ancak belirli türler için (açıklamalı veya açıklama taşıyan) bir bileşen taraması ve bunların FactoryBeanher biri için yapılandırılmış bir şey vardır .
Oliver Drotbohm

2
Eski bir iş parçacığı hakkında yorum yaptığım için üzgünüm ama merak ediyordum ... Depo vekilleri tek nesneler mi? Kodumuzun bir repo yöntemi çağırmaya çalıştığı bir sorun görüyoruz, ancak hiçbir zaman proxy üzerinde arama yapamayacak gibi görünüyor. Sadece takılıyor. Acaba meşgul olan bir bekar mı bekliyor?
iu.david
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.