Во-первых, не происходит генерации кода, что означает: нет CGLib, вообще нет генерации байт-кода. Фундаментальный подход заключается в том, что экземпляр прокси JDK создается программно с использованием ProxyFactory
API Spring для поддержки интерфейса, а 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 контейнеров мы, конечно , затем построил интеграции с конфигурацией Spring Java, XML - пространство имен, но и расширение CDI , так что Spring Data может использоваться в простых сценариях CDI.
@Repository
аннотированные интерфейсы в первую очередь? Глядя наRepositoryFactorySupport#getRepository()
show, он принимает класс интерфейса в качестве параметра, поэтому его нужно найти где-нибудь еще. Я особенно пытаюсь выяснить, как найти аннотированный интерфейс и автоматически создать прокси-компонент JDK, который реализует интерфейс, очень похоже на spring-data, но для конкретной цели приложения, не связанной с репозиториями.RepositoryComponentProvider
. Не происходит никаких автоматических действий, кроме сканирования компонентов для определенных типов (аннотированных или несущих аннотацию) иFactoryBean
настройки для каждого из них.