Spring AOP를 기반으로 동작하며 RespositoryFactorySupport에서 프록시를 생성한다.
생성된 프록시가 bean으로 등록되어 주입되는 것.
2. 프록시 패턴
Proxy와 Real Subject가 공유하는 인터페이스가 있고, Client는 해당 인터페이스 타입으로 Proxy를 사용한다.
Client는 Proxy를 거쳐서 Real Subject를 사용하기 때문에 Proxy는 Real Subject에 대한 접근 관리, 부가기능 제공, 리턴값 변경을 할 수 있다.
Real Subject는 자신이 해야할 일만 하면서(단일 책임 원칙) Proxy를 사용해서 부가적인 기능(접근 제한, 로깅, 트랜잭션 등)을 제공할 때 이런 패턴을 주로 사용한다.
예시
차례대로 Subject(Interface), Real Subject, 그리고Proxy에 해당하는 예시 코드이다.
public interface CarService {
void startEngine(CarModel model);
}
public class RealCarService implements CarService {
@Override
public void startEngine(CarModel model) {
System.out.println(model.getModel() + " engine starts...");
}
}
public class ProxyCarService implements CarService {
private final CarService carService;
public ProxyCarService(CarService carService) {
this.carService = carService;
}
@Override
public void startEngine(CarModel model) {
System.out.println("Proxy has taken over.");
carService.startEngine(model);
System.out.println("Now we are letting you go.");
}
}
먼저 Real Subject의 코드를 실행해보면
class CarServiceTest {
private CarService carService = new RealCarService();
@Test
void startEngine() {
CarModel model = new CarModel("Avante");
carService.startEngine(model);
}
}
이제 Proxy를 사용해 코드를 실행해보자.
class CarServiceTest {
private CarService carService = new ProxyCarService(new RealCarService());
@Test
void startEngine() {
CarModel model = new CarModel("Avante");
carService.startEngine(model);
}
}
이번엔 프록시에서라도 차 모델을 G90으로 변경해보자.
public class ProxyCarService implements CarService {
private final CarService carService;
public ProxyCarService(CarService carService) {
this.carService = carService;
}
@Override
public void startEngine(CarModel model) {
System.out.println("G90 engine starts...");
}
}
기존의 메소드를 사용하는 것 뿐만 아니라 아예 다른 작업도 가능하는 것을 잊지 말자.
3. 다이나믹 프록시 실습
다이나믹 프록시란, 런타임에 특정 인터페이스들을 구현하는 클래스 또는 인스턴스를 만드는 기술이다.
4부. 다이나믹 프록시
(다이나믹 프록시 또한 리플렉션의 일부이다.)
1. 스프링 데이터 JPA는 어떻게 동작하나?
2. 프록시 패턴
Proxy
와Real Subject
가 공유하는 인터페이스가 있고,Client
는 해당 인터페이스 타입으로Proxy
를 사용한다.Client
는Proxy
를 거쳐서Real Subject
를 사용하기 때문에Proxy
는Real Subject
에 대한 접근 관리, 부가기능 제공, 리턴값 변경을 할 수 있다.Real Subject
는 자신이 해야할 일만 하면서(단일 책임 원칙)Proxy
를 사용해서 부가적인 기능(접근 제한, 로깅, 트랜잭션 등)을 제공할 때 이런 패턴을 주로 사용한다.예시
차례대로
Subject
(Interface),Real Subject
, 그리고Proxy
에 해당하는 예시 코드이다.먼저
Real Subject
의 코드를 실행해보면이제
Proxy
를 사용해 코드를 실행해보자.이번엔 프록시에서라도 차 모델을 G90으로 변경해보자.
기존의 메소드를 사용하는 것 뿐만 아니라 아예 다른 작업도 가능하는 것을 잊지 말자.
3. 다이나믹 프록시 실습
런타임에
특정 인터페이스들을 구현하는 클래스 또는 인스턴스를 만드는 기술이다.컴파일 타임에
프록시 패턴을 적용해본 것이다. 차이를 구분해야한다.예시
리플렉션에서 봤듯,
invoke()
의 proxy는 우리가 원하는 proxy 이고,Object[] args
는 arguments로,Real Subject
에 arguments를 넘겨주고 실행한다면 메소드가 하는 일을 그대로 실행한다.이제
Proxy
의 역할을 하도록 코드를 변경해보자. 출력을 하면 무슨 값이 나올까?모든 메소드에 위의 로직이 실행되게 된다...
굳이 바꾼다면 다음과 같겠으나, 프록시 패턴을 각각이 사용할 매소드가 많아지고 구조가 복잡해질 수록 사용이 어려워질 것이다.
4. 클래스의 프록시가 필요하다면?
예시
마찬가지로 앞뒤로 로직을 추가할 수 있다.
예시
변경된게 없는 RealCarService를 하위클래스를 만들어서 실행하는 방법.
이와 같이 클래스 기반의 프록시도 사용이 가능하다.
5. 다이나믹 프록시 정리
@OneToMany
등의 Many로 끝났을 때는 lazy.