스프링에서 AOP 프록시는 JDK 동적 프록시 또는 CGLIB 프록시
Spring의 AOP는 기본적으로 프록시 방식으로 동작하도록 되어 있는데, Spring에서 AOP를 활용하기 위해서는 @EnableAspectJAutoProxy 어노테이션을 붙여주어야 하며, 이에 대한 옵션으로 proxyTargetClass
Spring은 Java 언어 차원에서 제공하는 자동 프록시 생성기를 통해 직접 프록시 객체를 생성한 후에 특별한 처리를 해주는데, 이를 JDK 동적 프록시 또는 JDK 다이나믹 프록시라고 함
Spring은 프록시를 구현할 때 프록시를 구현한 객체(RateDiscountServiceProxy)를 마치 실제 빈(RateDiscountService)인 것처럼 포장하고, 2개의 빈을 모두 등록하는 것이 아니라 실제 빈을 프록시가 적용된 빈으로 바꿔치기함
이러한 방식이 가능한 이유는 프록시 구현 대상(RateDiscountService)이 인터페이스(DiscountService)를 구현하고 있으며, Spring이 프록시 구현체(RateDiscountServiceProxy)를 만들때 프록시 대상과 동일한 인터페이스(DiscountService)를 구현하도록 했기 때문임
즉, 프록시 대상(RateDiscountService)과 프록시 구현체(RateDiscountServiceProxy) 모두 동일한 인터페이스(DiscountService) 타입 및 구현체이기 때문에 기존의 RateDiscountService 빈을 RateDiscountServiceProxy로 바꿔치기 하고, 빈 후처리기를 통해 이미 정의된 의존 관계 역시 바꿀 수 있음

기존에는 왼쪽과 같이 실제 빈과 Proxy 빈 2개가 스프링 컨테이너에 등록되었다면, Spring이 JDK 동적 프록시를 구현할 때에는 Proxy 빈을 실제 빈처럼 구현하고 기존의 빈을 대체
이러한 방식은 괜찮아 보이지만 만약 실제 빈을 직접 참조하고 있는 경우라면 문제가 발생
위의 예제에서 문제가 발생하지 않은 이유는 실제 빈(RateDiscountService)이 DiscountService라는 인터페이스에 의존하고 있고, DiscountController에서도 DiscountService에 의존
Spring이 새롭게 추가한 RateDiscountServiceProxy는 DiscountService 인터페이스를 구현한 클래스이지 RateDiscountService를 상속받은 클래스가 아니다. 그래서 RateDiscountService 타입의 빈을 찾을 수 없어 에러가 발생

또한 JDK dynamic proxy는 인터페이스를 기반으로 프록시 객체를 생성하는데, 인터페이스를 구현한 클래스가 아니면 프록시 객체를 생성할 수 없음
즉, JDK 동적 프록시는 다음과 같은 두 가지 한계점을 가지게 됨
하지만 실제 개발을 하다보면 인터페이스 없이 구체 클래스에 의존하는 경우도 많은데, AOP를 적용하기 위해 모든 빈들에게 인터페이스를 만들어주는 것은 상당히 번거로움
또한 구체 클래스에 의존해야 하는 경우에는 빈을 찾을 수 없어서 에러가 발생하므로 대처가 어려움
이러한 이유로 Spring은 JDK 동적 프록시 방식이 아닌 또 다른 프록시 구현 방식을 구현
기본 생성자를 필요로 하며, 생성자가 2번 호출되고 final 클래스나 final 메소드면 안된다는 제약
@EnableAspectJAutoProxy의 proxyTargetClass
스프링 프레임워크는 프록시를 구현할 때 기존의 방식처럼 인터페이스를 구현하도록 할 것인지(JDK 동적 프록시) 또는 해당 클래스를 바이트 조작하여 직접 구현하도록 할 것인지(CGLib)에 대한 옵션을 제공하고 있는데, 이것이 바로 proxyTargetClass
일반적으로 인터페이스 주입에 의한 문제를 예방하고자 proxyTargetClass를 true로 주는 경우가 많은데, SpringBoot를 사용하고 있다면 더이상 이러한 옵션을 부여하지 않아도 된다. 왜냐하면 SpringBoot에서는 CGLib 라이브러리가 안정화되었다고 판단하여 proxyTargetClass 옵션의 기본값을 true로 사용
모르겠다....