진짜는 프록시(Proxy)다
아래 소스코드들의 출처는 spring-project임을 밝힙니다.
spring-data-jpa는 2.6.x를 기준으로 작성했습니다.
엔티티의 타입이 Country인 Country카지노 게임 인터페이스를 예시로 정의했다.
publicinterfaceCountry카지노 게임extendsJpa카지노 게임<Country, Long {
Country findByName(String name);
...
}
간단히인터페이스로만 선언하면 되기 때문에편리하다. 그런데직접구현하지않은save(), saveAll(), findAll() 등같은메서드들은대체어디서나온걸까? 라는 궁금증을 가진적이 있을까.
비밀은 SimpleJpa카지노 게임에 있다. 지난 글'Jpa카지노 게임는 Save와 Update를 어떻게 구분하는지'에서 SimpleJpa카지노 게임에 대해서 간단하게 언급했었다.
인터페이스로 선언된 Jpa카지노 게임의 save()를 호출하면 내부적으로 SimpleDataJpa카지노 게임의 save()를 호출한다.
Country카지노 게임인터페이스는자체는사실껍데기에불과하다. spring-data-jpa에는JPA카지노 게임를생성하는Jpa카지노 게임Factory 클래스가존재하는데개발자가정의한Country카지노 게임 인터페이스를참조하여Jpa카지노 게임를대신구현하는역할을한다.
Jpa카지노 게임Factory는 spring-data-commons 모듈의 카지노 게임FactorySupport를 확장하고 있다.
importorg.springframework.data.카지노 게임.core.support.카지노 게임FactorySupport;
publicclassJpa카지노 게임Factory extends카지노 게임FactorySupport{
...
카지노 게임FactorySupport는 전달받은 카지노 게임 인터페이스로 Proxy 인스턴스를 생성하는 추상 클래스이다.
packageorg.springframework.data.카지노 게임.core.support;
publicabstract class카지노 게임FactorySupport implementsBeanClassLoaderAware, BeanFactoryAware {
...
카지노 게임FactorySupport를 확장하여 다양한 spring-data-XXX에서 카지노 게임를 생성한다. 카지노 게임FactorySupport에는 get카지노 게임라는 카지노 게임 인스턴스를 생성하는 메서드가 기본으로 정의돼 있다. 이 메서드는카지노 게임 인터페이스를 구현한 Proxy를생성한다. Jpa카지노 게임Factory는 부모 클래스의 메서드인 get카지노 게임를 상속 받는다.
public<T T get카지노 게임(Class<T 카지노 게임Interface, 카지노 게임Fragments fragments) {
//첫 번째 파라미터 카지노 게임Interface로 Country카지노 게임가 전달된다.
...
ProxyFactory result = new ProxyFactory();
result.setTarget(target);
result.setInterfaces(카지노 게임Interface, 카지노 게임.class, TransactionalProxy.class);
// 카지노 게임Interface로 전달된 Country카지노 게임의 인터페이스를 구현한다.
...
T카지노 게임 = (T) result.getProxy(classLoader);
...
return repository; // Proxy 인스턴스를 반환한다.
}
대신 spring-data-jpa는Jpa카지노 게임Factory가 추상 메서드인 get카지노 게임BaseClass를SimpleJpa카지노 게임.class를반환하도록오버라이드했다.
@Override
protectedClass<? get카지노 게임BaseClass(카지노 게임Metadata metadata) {
returnSimpleJpa카지노 게임.class;
}
protectedabstractClass<? get카지노 게임BaseClass(카지노 게임Metadata metadata);
...
메서드명세를살펴보면Base Class는실제카지노 게임 인스턴스를지원하는클래스이다. 즉SimpleJpa카지노 게임는실제로생성된Jpa카지노 게임 인스턴스를지원하는(Backing)인스턴스의클래스(타입)이된다.
Returns the base class backing the actual repository instance.
Make sure *getTarget카지노 게임(카지노 게임Information) returns an instance of this class.
출처: docs.spring.io
get카지노 게임BaseClass가반환하는Base class는get카지노 게임Information에서카지노 게임Information 인스턴스를조립할때전달된다. 카지노 게임Information은 말 그대로 카지노 게임의 정보를 담고있다(예: 엔티티의 타입은 무엇인지, Base Class는 무엇인지 등등).
private카지노 게임Information get카지노 게임Information(카지노 게임Metadata metadata,
카지노 게임Composition composition) {
....
return카지노 게임InformationCache.computeIfAbsent(cacheKey, key - {
Class<? baseClass= repositoryBaseClass.orElse(get카지노 게임BaseClass(metadata));
//get카지노 게임BaseClass를 호출해 Base Class를 가져온다(SimpleJpa카지노 게임.class).
returnnew Default카지노 게임Information(metadata, baseClass, composition);
});
}
...
하나 더! API 명세에서 getTarget카지노 게임가 반환하는 인스턴스의 클래스가 Base Class와 같아야 한다고 했다.
Make sure *getTarget카지노 게임(카지노 게임Information) returns an instance of this class.
카지노 게임Information은getTarget카지노 게임의인자로Base Class 정보를전달해Target카지노 게임 인스턴스의Class 타입을결정한다. Jpa카지노 게임Factory의경우Target카지노 게임가SimpleJpa카지노 게임.class가되겠다.
Query Proxy를 지원하는 카지노 게임 인스턴스라고 한다.
Create a 카지노 게임 instance as backing for the query proxy.
출처: docs.spring.io
앞서 카지노 게임FactorySupport에는 실질적인 카지노 게임 인스턴스를 생성하는 get카지노 게임가 메서드가 정의돼 있다고 했다. 메서드를 훑어보면서 Target카지노 게임에 대해서 알아보자(아래 코드의 코멘트 (1), (2), (3). (4)를 읽으면서 따라가 보자)
public<T T get카지노 게임(Class<T 카지노 게임Interface, 카지노 게임Fragments fragments) {
...
카지노 게임Information information =get카지노 게임Information(metadata, composition);
//(1) Base Class 정보가 담긴 카지노 게임Information을 가져온다.
...
Object target = getTarget카지노 게임(information);//(2) Target카지노 게임를 생성한다.
...
ProxyFactory result = new ProxyFactory();
result.setTarget(target);//(3) Target카지노 게임는 Proxy의 target 인자로 전달된다.
result.setInterfaces(카지노 게임Interface, 카지노 게임.class, TransactionalProxy.class);
...
T카지노 게임 = (T) result.getProxy(classLoader);
...
returnrepository; //(4) Proxy 카지노 게임를 반환한다.
}
아하! Proxy 인스턴스의 target이 Target카지노 게임였구나! 즉 Proxy로 생성된 카지노 게임 인스턴스의 target 인스턴스가 SimpleJpa카지노 게임의 인스턴스였다는걸 알게 됐다. 그렇다면 SimpleJpa카지노 게임가 뒤에서 Jpa카지노 게임 인터페이스의 실 구현체를 제공한다는 의미이다.
1. 최종적으로 Bean으로 생성되는 Country카지노 게임는 Proxy 인스턴스이다(Proxy 카지노 게임).
2. Jpa카지노 게임는 Proxy 인스턴스의 Target을 SimpleJpa카지노 게임.class의 인스턴스로 주입한다.
3. Proxy 카지노 게임 인스턴스 내부에서 SimpleJpa카지노 게임(target)가 실 구현체를 실행한다.