CGLIB를 사용하려면 CGLIB 라이브러리가 별도로 필요했다.
스프링은 CGLIB 라이브러리를 스프링 내부에 함께 패키징해서 별도의 라이브러리 추가 없이 CGLIB를 사용할 수 있게 되었다.
스프링 4.0부터 CGLIB의 기본 생성자가 필수인 문제가 해결되었다.
objenesis 라는 특별한 라이브러리를 사용해서 기본 생성자 없이 객체 생성이 가능하게 하였다.
스프링 4.0부터 CGLIB의 생성자 2번 호출 문제가 해결되었다.
이것도 역시 objenesis 라는 특별한 라이브러리 덕분에 가능해졌다.
이제 생성자가 1번만 호출된다.
스프링 부트 2.0 버전부터 CGLIB를 기본으로 사용하도록 했다.
이렇게 해서 구체 클래스 타입으로 의존관계를 주입하는 문제를 해결했다.
스프링 부트는 별도의 설정이 없다면 AOP를 적용할 때 기본적으로 proxyTargetClass = true로 설정해서 사용한다.
따라서 인터페이스가 있어도 JDK 동적 프록시를 사용하는 것이 아니라 항상 CGLIB를 사용해서 구체 클래스를 기반으로 프록시를 생성한다.
물론 스프링은 다음과 같이 설정하면 JDK 동적 프록시도 사용할 수 있다.application properties spring.aop.proxy-target-clss=false
스프링은 최종적으로 스프링 부트 2.0에서 CGLIB를 기본으로 사용하도록 결정했다.
CGLIB를 사용하면 JDK 동적 프록시에서 동작하지 않는 구체 클래스 주입이 가능하다.
여기에 추가로 CGLIB의 단점들이 이제는 많이 해결되었다.
CGLIB의 남은 문제라면 final 클래스나 fianl 메소드가 있는데 AOP를 적용할 대상에는 final 클래스나 final 메소드를 잘 사용하지는 않으므로 이 부분은 크게 문제가 되지는 않는다.
개발자 입장에서 보면 사실 어떤 프록시 기술을 사용하던 상관이 없다.
JDK 동적 프록시던 CGLIB 프록시던 또는 어떤 새로운 프록시 기술을 사용해도 된다.
심지어 클라이언트 입장에서 어떤 프록시 기술을 사용하는지 모르고 잘 동작하는 것이 가장 좋다.
단지 문제 없고, 개발하기에 편리하면 되는 것이다.