JDK 동적 프록시는 JDK에서 프록시 패턴을 구현한 것으로, 인터페이스 대상으로 프록시를 생성할 수 있다. 프록시 객체는 타겟 인터페이스를 구현한 구현체이다. InvocationHandler 인터페이스를 구현해서 만들 수 있음.
제약사항은 타겟이 인터페이스가 있어야 한다는 것이다.
CGLIB 방식 프록시는 타겟 클래스를 상속하여 만든 프록시이다. MethodInterceptor 인터페이스 구현하여 만들 수 있음
제약으로는 부모 클래스 생성자를 체크해야 한다. 자식 생성자에서 부모 생성자를 호출하기 떄문.
final 클래스는 상속할 수 없어서 프록시 생성 불가. final 메서드도 상속할 수 없어 프록시 적용 안됨.
스프링에서는 타겟이 인터페이스냐 클래스냐에 따라 자동으로 프록시를 생성해주는 프록시 팩토리 Proxy Factory를 사용한다.
하지만 Spring Boot 에서는 기본으로 proxyTargetClass=true 세팅되어 있는데, 타겟이 인터페이스 여부를 무시하고 무조건 CGLIB 로 프록시를 생성하는 설정이다.
옵션과 무관하게 인터페이스가 없으면 JDK 동적 프록시를 적용할 수 없으므로 CGLIB를 사용한다.
기본값이 구체클래스로 기반 CGLIB 되어 있는 이유는 동적 프록시 한계점이 있다. @Autowired UserServiceImpl userservice 로 되어있는 경우 구현체를 Bean으로 주입해야하는데, proxy 객체는 같은 인터페이스의 다른 구현체이기 때문에 타겟 클래스로 타입캐스팅에 실패해서 주입이 안된다.