You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ConcreteService를 상속받아서 $$EnhancerByCGLIB를 동적으로 만들게 된다.
실행 결과
interceptor 먼저 찍고
ConcreteService 는 인터페이스가 없는 구체 클래스이다. 여기에 CGLIB를 사용해서 프록시를 생성해보자.
Enhancer : CGLIB는 Enhancer를 사용해서 프록시를 생성한다.
enhancer.setSuperclass(ConcreteService.class) : CGLIB는 구체 클래스를 상속 받아서 프록시를 생성할 수 있다. 어떤 구체 클래스를 상속받을지 지정한다.
enhancer.setCallback(new TimeMethodInterceptor(target)) : 프록시에 적용할 실행 로직을 할당한다.
enhancer.create() : 프록시가 생성한다. 앞서 설정한 enhancer.setSuperclass(ConcreteService.class) 에서 지정한 클래스를 상속받아서 프록시가 만들어진다.
JDK 동적 프록시는 인터페이스를 구현 (implement)해서 프록시를 만든다. CGLIB는 구체 클래스를 상속(extends) 해서 프록시를 만든다.
실행결과
CGLIB가 생성한 프록시 클래스 이름
CGLIB를 통해서 생성된 클래스의 이름을 확인해보자.
다음과 같은 규칙으로 생성된다.
대상클래스$$EnhancerByCGLIB$$임의코드
참고로 다음은 JDK Proxy 가 생성한 클래스 이름이다.
proxyClass=class com.sun.proxy.$Proxy1
그림으로 정리
CGLIB 제약
클래스 기반 프록시는 상속을 사용하기 때문에 몇가지 제약이 있다.
부모 클래스의 생성자를 체크해야 한다. → CGLIB는 자식 클래스를 동적으로 생성하기 때문에 기본 생성자가 필요하다.
클래스에 final 키워드가 붙으면 상속이 불가능하다. → CGLIB에서는 예외가 발생한다.
메서드에 final 키워드가 붙으면 해당 메서드를 오버라이딩 할 수 없다. → CGLIB 에서는 프록시 로직이 동작하지 않는다.
참고
CGLIB를 사용하면 인터페이스가 없는 V2 애플리케이션에 동적 프록시를 적용할 수 있다. 그런데 지금 당장 적용하기에는 몇가지 제약이 있다. V2 애플리케이션에 기본 생성자를 추가하고 의존관계를 setter 를 사용해서 주입하면 CGLIB를 적용할 수 있다. 하지만 다음에 학습하는 ProxyFactory 를 통해서 CGLIB를 적용하면 이런 단점을 해결하고 또 편리하기 때문에 애플리케이션에 CGLIB로 프록시를 적용하는 것은 조금 뒤에 알아보겠다.
정리
남은 문제
인터페이스가 있는 경우에는 JDK 동적 프록시를 적용하고 그렇지 않은 경우에는 CGLIB를 적용하려면 어떻게 해야할까?
두 기술을 함께 사용할 때 부가기능을 제공하기 위해서 JDK 동적 프록시가 제공하는 InvocationHandler 와 CGLIB가 제공하는 MethodInterceptor 를 각각 중복으로 만들어서 관리해야 할까?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
CGLIB - 소개
CGLIB : Code Generator Library
참고로 우리가 CGLIB를 직접 사용하는 경우는 거의 없다. 이후에 설명할 스프링의
ProxyFactory라는 것이 이 기술을 편리하게 사용하게 도와주기 때문에 너무 깊이있게 파기보다는 CGLIB가 무엇인지 대략 개념만 잡으면 된다.예제 코드를 CGLIB 를 간단히 이해해보자.
공통 예제 코드
앞으로 다양한 상황을 설명하기 위해서 먼저 공통으로 사용할 예제코드를 만들어보자.
ServiceInterface,ServiceImplConcreteServiceServiceInterface
ServiceImpl
ConcreteService
CGLIB - 예제코드
InvocationHandler를 제공했듯이 CGLIB는MethodInterceptor를 제공한다.MethodInterceptor - CGLIB 제공
obj: CGLIB 가 적용된 객체method: 호출된 메서드args: 메서드를 호출하면서 전달된 인수proxy: 메서드 호출에 사용(빠르게)TimeMethodInterceptor
TimeMethodInterceptor는MethodInterceptor인터페이스를 구현해서 CGLIB 프록시의 실행 로직을 정의한다.Object target: 프록시가 호출할 실제 대상proxy.invoke(target, args): 실제 대상을 동적으로 호출한다.method를 사용해도 되지만 CGLIB는 성능상MethodProxy proxy를 사용하는 것을 권장한다.Proxy > cglib > CglibTest
실행 결과
ConcreteService는 인터페이스가 없는 구체 클래스이다. 여기에 CGLIB를 사용해서 프록시를 생성해보자.Enhancer: CGLIB는Enhancer를 사용해서 프록시를 생성한다.enhancer.setSuperclass(ConcreteService.class): CGLIB는 구체 클래스를 상속 받아서 프록시를 생성할 수 있다. 어떤 구체 클래스를 상속받을지 지정한다.enhancer.setCallback(new TimeMethodInterceptor(target)): 프록시에 적용할 실행 로직을 할당한다.enhancer.create(): 프록시가 생성한다. 앞서 설정한enhancer.setSuperclass(ConcreteService.class)에서 지정한 클래스를 상속받아서 프록시가 만들어진다.JDK 동적 프록시는 인터페이스를 구현 (implement)해서 프록시를 만든다. CGLIB는 구체 클래스를 상속(extends) 해서 프록시를 만든다.
실행결과
CGLIB가 생성한 프록시 클래스 이름
CGLIB를 통해서 생성된 클래스의 이름을 확인해보자.
다음과 같은 규칙으로 생성된다.
대상클래스$$EnhancerByCGLIB$$임의코드참고로 다음은 JDK Proxy 가 생성한 클래스 이름이다.
proxyClass=class com.sun.proxy.$Proxy1그림으로 정리
CGLIB 제약
final키워드가 붙으면 상속이 불가능하다. → CGLIB에서는 예외가 발생한다.final키워드가 붙으면 해당 메서드를 오버라이딩 할 수 없다. → CGLIB 에서는 프록시 로직이 동작하지 않는다.참고
CGLIB를 사용하면 인터페이스가 없는 V2 애플리케이션에 동적 프록시를 적용할 수 있다. 그런데 지금 당장 적용하기에는 몇가지 제약이 있다. V2 애플리케이션에 기본 생성자를 추가하고 의존관계를
setter를 사용해서 주입하면 CGLIB를 적용할 수 있다. 하지만 다음에 학습하는ProxyFactory를 통해서 CGLIB를 적용하면 이런 단점을 해결하고 또 편리하기 때문에 애플리케이션에 CGLIB로 프록시를 적용하는 것은 조금 뒤에 알아보겠다.정리
남은 문제
InvocationHandler와 CGLIB가 제공하는MethodInterceptor를 각각 중복으로 만들어서 관리해야 할까?Beta Was this translation helpful? Give feedback.
All reactions