39

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

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

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

  1. Как это реализация хранилища класс, сгенерированный во время выполнения & методы, внедряемые и введенные?
  2. Имеет ли данные Spring JPA использовать CGlib или любые библиотеки манипулирования байткодами для реализации методов и динамического впрыска?

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

ответ

58

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

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

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

Создание этих прокси-объектов инкапсулируется в стандартную реализацию шаблона Factory на основе 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 extension, так что Spring Data можно использовать в простых сценариях CDI.

+1

Привет, Оливер, можете ли вы рассказать о том, как весна обнаруживает аннотированные интерфейсы '@ Repository' в первую очередь? Глядя на 'RepositoryFactorySupport # getRepository()', покажите, что он принимает класс интерфейса как параметр, поэтому его нужно найти где-то в другом месте. Я особенно стараюсь выяснить, как найти аннотированный интерфейс и автоматически генерировать прокси-сервер JDK, который реализует интерфейс, очень похожий на весенние данные, но для конкретной цели приложения, не связанной с репозиториями. –

+0

Возможно, вы захотите взглянуть на ['RepositoryComponentProvider'] (https://github.com/spring-projects/spring-data-commons/blob/0237760345faa011bdc6639ec838790be3d41e9b/src/main/java/org/springframework/data/repository /config/RepositoryComponentProvider.java#L60-L79). Нет никаких автоматических событий, но просмотр компонентов для определенных типов (аннотированный или несущий аннотацию) и «FactoryBean», настроенный для каждого из них. –