Подтвердить что ты не робот

Как реализованы Spring репозитории данных?

В течение некоторого времени я работаю с репозиторием Data JPA в моем проекте, и я знаю следующие пункты:

  • В интерфейсах репозитория мы можем добавить такие методы, как findByCustomerNameAndPhone() (предполагая, что customerName и phone - это поля в объекте домена).
  • Затем Spring обеспечивает реализацию путем реализации вышеупомянутых методов интерфейса репозитория во время выполнения (во время запуска приложения).

Мне интересно, как это было закодировано, и я просмотрел исходный код и API-интерфейс Spring JPA, но я не смог найти ответы на следующие вопросы:

  • Как создается класс реализации репозитория во время выполнения и внедряемые и внедряемые методы?
  • Использует ли Spring данные JPA использовать CGlib или любые библиотеки манипулирования байткодами для реализации методов и динамического впрыска?

Не могли бы вы помочь с вышеуказанными запросами, а также предоставить любую поддерживаемую документацию?

4b9b3361

Ответ 1

Прежде всего, генерации кода не происходит, что означает: нет CGLib, без генерации байтового кода. Фундаментальный подход заключается в том, что экземпляр прокси-сервера JDK создается программно с использованием API Spring ProxyFactory для поддержки интерфейса, а MethodInterceptor перехватывает все вызовы экземпляра и направляет метод в соответствующие места:

  • Если репозиторий был инициализирован с помощью специальной части реализации (см. эту часть справочной документации для получения подробной информации), а вызванный метод реализованный в этом классе, вызов маршрутизируется там.
  • Если метод является методом запроса (см. DefaultRepositoryInformation для определения того, как это определено), механизм выполнения конкретных запросов магазина запускается и выполняет запуск запроса для этого метода при запуске. Для этого существует механизм разрешения, который пытается идентифицировать явно объявленные запросы в разных местах (используя @Query в методе, JPA с именем запросов), в конце концов, возвращается к выводу запроса из имени метода. Для обнаружения механизма запроса см. JpaQueryLookupStrategy. Логику синтаксического анализа для вывода запроса можно найти в PartTree. Конкретный перевод хранилища в фактический запрос можно увидеть, например. в JpaQueryCreator.
  • Если ни одно из вышеприведенных действий не применяется, выполненный метод должен быть реализован базовым классом репозитория, определенным хранилищем (SimpleJpaRepository в случае JPA), и вызов направляется в экземпляр этого.

Метод-перехватчик, реализующий эту логику маршрутизации, QueryExecutorMethodInterceptor, логику маршрутизации высокого уровня можно найти здесь.

Создание этих прокси-объектов инкапсулируется в стандартную реализацию шаблона Factory на основе Java. Создание прокси-сервера высокого уровня можно найти в RepositoryFactorySupport. Затем реализация хранилища добавляет необходимые компоненты инфраструктуры, поэтому для JPA вы можете продолжать писать и писать такой код:

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

Причина, по которой я упоминаю, что явно заключается в том, что должно стать ясно, что в ее основе ничто из этого кода не требует, чтобы контейнер Spring запускался в первую очередь. Он нуждается в Spring в качестве библиотеки на пути к классам (потому что мы предпочитаем не изобретать колесо), но в целом не является агностиком контейнера.

Чтобы упростить интеграцию с контейнерами DI, мы, конечно же, построили интеграцию с конфигурацией Java Spring, пространство имен XML, а также расширение CDI, так что Spring Данные могут использоваться в простых сценариях CDI.