ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] 동적 프록시 기술 - CGLIB
    Spring 2022. 6. 16. 22:36

    JDK 동적프록시는 인터페이스를 기반으로 프록시 클래스를 만들기 때문에

    인터페이스가 없다면 사용할 수 없었다.

     

    따라서 인터페이스 없이 구체 클래스만을 가지고 동적프록시를 만드는 방법이

    CGLIB를 활용하는 방법이다.

    (CGLIB는 외부 오픈소스 라이브러리였으나 스프링 내부 소스 코드에 포함되었다. - 별도 추가 X)

     

    JDK 동적 프록시에서 InvocationHandler를 구현했던 것 처럼

    CGLIB는 MethodInterceptor을 구현한다.

    public interface MethodInterceptor extends Callback {
     	Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable;
    }

    이때 obj는 CGLIB가 적용된 객체

    method는 호출된 메서드

    args는 메서드를 호출하면서 전달된 인수

    proxy는 메서드 호출에 사용하는 인수이다.

     

    MethodInterceptor를 구현하는 방법은 JDK 동적프록시와 동일하나 method.invoke()가 아닌

    proxy.invoke()를 사용한다 (method를 사용해도 되나 성능 상 proxy 사용을 권장하고 있음)

     

    이제 CGLIB를 활용하는 방법을 알아보면

    // CGLIB는 Enhancer를 사용해서 프록시를 생성한다.
    Enhancer enhancer = new Enhancer();
    
    // CGLIB는 구체클래스를 상속받아 프록시를 만드므로 상속받을 클래스를 지정한다.
    enhancer.setSuperclass(구체클래스.class);
    
    // 프록시에 적용할 실행로직을 할당한다.
    enhancer.setCallback(new MethodInterceptor구현체(실제객체));
    
    // 앞서 지정한 클래스를 상속받아 프록시를 생성한다.
    구체클래스 proxy = (구체클래스)enhancer.create();

     

    CGLIB는 대상클래스$$EnhancerByCGLIB$$임의코드 의 형태로 프록시 클래스를 생성한다.

     

    CGLIB의 경우 상속을 사용하기 때문에 몇가지 제약이 있다.

    부모 클래스의 생성자를 체크해야한다. (기본 생성자가 필요하다.)

    클래스에 final 키워드가 붙으면 상속이 불가능하여 예외가 발생한다.

    메서드에 final 키워드가 붙으먼 오버라이딩이 불가능하여 프록시 로직이 동작 안한다.

     

    인터페이스를 기반한 JDK 동적 프록시와 CGLIB라는 두가지 기술이 있음에도

    아직 해결하지 못하는 문제들이 남아있다.

     

    이를 해결하기 위해 스프링이 제공하는 ProxyFactory를 활용하게 된다.

     

     

     

    [참고 : 인프런 - 스프링 핵심 원리 - 고급편]

Designed by Tistory.