SpringData 저장소는 실제로 어떻게 구현됩니까?


111

나는 한동안 내 프로젝트에서 SpringData JPA 저장소로 작업 해 왔으며 아래 사항을 알고 있습니다.

  • 저장소 인터페이스에서 findByCustomerNameAndPhone()( 도메인 개체의 필드 라고 가정) customerName과 같은 메서드를 추가 할 수 있습니다 phone.
  • 그런 다음 Spring은 런타임에 위의 저장소 인터페이스 메서드를 구현하여 구현을 제공합니다 (애플리케이션 실행 중).

이것이 어떻게 코딩되었는지에 관심이 있고 Spring JPA 소스 코드 및 API를 살펴 보았지만 아래 질문에 대한 답변을 찾을 수 없습니다.

  1. 저장소 구현 클래스는 런타임 및 메소드에서 어떻게 생성되고 삽입됩니까?
  2. SpringData JPA는 메소드를 구현하고 동적으로 주입하기 위해 CGlib 또는 바이트 코드 조작 라이브러리를 사용합니까?

위의 질의에 도움을 주시고 지원되는 문서를 제공해 주시겠습니까?

답변:


144

우선, 진행중인 코드 생성이 없습니다. 즉, CGLib도없고 바이트 코드도 생성되지 않습니다. 기본적인 접근 방식은 JDK 프록시 인스턴스가 Spring의 ProxyFactoryAPI를 사용하여 프로그래밍 방식으로 생성 되어 인터페이스 MethodInterceptor를 지원하고 인스턴스에 대한 모든 호출을 가로 채서 메서드를 적절한 위치로 라우팅하는 것입니다.

  1. 리포지토리가 사용자 지정 구현 부분 (자세한 내용 은 참조 문서의 해당 부분 참조)으로 초기화되고 호출 된 메서드가 해당 클래스에서 구현 된 경우 호출이 여기로 라우팅됩니다.
  2. 메서드가 쿼리 메서드 인 경우 (확인 방법 참조 DefaultRepositoryInformation) 저장소 별 쿼리 실행 메커니즘은 시작시 해당 메서드에 대해 실행되도록 결정된 쿼리를 시작하고 실행합니다. 이를 위해 다양한 위치에서 명시 적으로 선언 된 쿼리를 식별하려는 해결 메커니즘이 마련되어 있습니다 ( @Query메소드에서 JPA 명명 된 쿼리 사용). 결국 메서드 이름에서 파생 된 쿼리로 대체됩니다. 쿼리 메커니즘 검색에 대해서는을 참조하십시오 JpaQueryLookupStrategy. 쿼리 파생에 대한 구문 분석 논리는에서 찾을 수 있습니다 PartTree. 실제 쿼리에 대한 상점 별 번역은에서 볼 수 있습니다 JpaQueryCreator.
  3. 위의 어느 것도 적용되지 않는 경우 실행되는 메소드는 저장소 별 저장소 기본 클래스 ( SimpleJpaRepositoryJPA의 경우)에 의해 구현 된 메소드 여야 하며 호출은 해당 인스턴스로 라우팅됩니다.

라우팅 로직을 구현하는 메소드 인터셉터는 여기QueryExecutorMethodInterceptor 에서 높은 수준의 라우팅 로직을 찾을 수 있습니다 .

이러한 프록시의 생성은 표준 Java 기반 Factory 패턴 구현으로 캡슐화됩니다. 고급 프록시 생성은에서 찾을 수 있습니다 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 확장 과의 통합을 구축하여 SpringData 를 일반 CDI 시나리오에서 사용할 수 있도록했습니다.


3
올리버 님, 스프링이 @Repository애노테이션이있는 인터페이스를 처음 발견하는 방법에 대해 자세히 설명해 주 시겠습니까? 보면 RepositoryFactorySupport#getRepository()이 다른 곳을 검색해야합니다 그래서 쇼는, 매개 변수로 인터페이스 클래스를 걸립니다. 저는 특히 주석이 달린 인터페이스를 찾고 인터페이스를 구현하는 JDK 프록시 빈을 자동으로 생성하는 방법을 알아 내려고 노력하고 있습니다. 이는 스프링 데이터와 매우 유사하지만 리포지토리와 관련이없는 애플리케이션 특정 목적을위한 것입니다.
Chris Rice

1
을 (를) 살펴볼 수 있습니다 RepositoryComponentProvider. 자동으로 일어나는 일은 없지만 컴포넌트는 특정 유형 (주석 또는 주석 포함)을 스캔하고 각 유형 FactoryBean에 대해 구성됩니다.
Oliver Drotbohm 2017

2
이전 스레드에 대해 댓글을 달아서 미안하지만 궁금한 점이 있습니다. 저장소가 싱글 톤 객체를 프록시합니까? 코드가 repo 메서드를 호출하려고하지만 프록시에서 호출 할 수없는 것 같습니다. 그냥 멈 춥니 다. 바쁜 싱글 톤을 기다리고 있는지 궁금합니다.
iu.david
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.