Перш за все, не відбувається генерація коду, а це означає: немає CGLib, взагалі немає генерації байт-кодів. Фундаментальний підхід полягає в тому, що проксі-екземпляр JDK створюється програмно за допомогою ProxyFactory
API Spring для резервного інтерфейсу та MethodInterceptor
перехоплює всі виклики до екземпляра та спрямовує метод у відповідні місця:
- Якщо репозиторій був ініціалізований за допомогою спеціальної частини реалізації (детальніше див. Цю частину довідкової документації ), а метод, що викликається, реалізований у цьому класі, виклик направляється туди.
- Якщо метод є методом запиту (див.
DefaultRepositoryInformation
Як це визначено), механізм виконання специфічного запиту заповнює і виконує запит, визначений для виконання цього методу при запуску. Для цього існує механізм роздільної здатності, який намагається ідентифікувати явно оголошені запити в різних місцях (використовуючи @Query
метод, JPA з іменами запитів), врешті повертаючись до виведення запиту з імені методу. Про механізм виявлення запиту див JpaQueryLookupStrategy
. Логіку розбору для виведення запиту можна знайти в PartTree
. Переклад конкретного магазину на фактичний запит можна побачити, наприклад, у JpaQueryCreator
.
- Якщо нічого із зазначеного вище не застосовується, виконаний метод повинен бути таким, який реалізований базовим класом сховища для конкретного магазину (
SimpleJpaRepository
у випадку JPA), і виклик перетворюється на екземпляр цього.
Метод перехоплювача, що реалізує цю логіку маршрутизації 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.
@Repository
спочатку помічені інтерфейси? Дивлячись наRepositoryFactorySupport#getRepository()
показ, що він приймає клас інтерфейсу як параметр, тому його треба виявити десь ще. Я особливо намагаюся розібратися, як знайти анотований інтерфейс і автоматично генерувати проксі-сервер JDK, який реалізує інтерфейс, дуже схожий на весняні дані, але для конкретної програми, не пов'язаної з Репозиторіями.