Springboot

JDK동적프록시/CGLIB

25G 2023. 8. 14. 18:07

JDK 동적 프록시

프록시패턴을 적용하기 위해서는 저거용대상의 숫자만큼 많은 프록시 클래스를 만들어야 했다.
프록시의 로직은 같은데 적용 대상만 차이가 있는것이다.

이 문제를 해결해 주는 것이 동적 프록시 기술이다.
동적 프록시 기술을 사용하면 개발자가 직접 프록시 클래스를 만들지 않아도 된다. 이름 그대로 프록시 객체를 동적으로
런타임에 개발자 대신만들어준다. 그리고 동적 프록시에 원하는 실행로직을 지정할 수 있다.
JDK동적 프록시는 인터페이스를 기반으로 프록시를 동적으로 만들어준다. 따라서 인터페이스가 필수이다.

JDK 동적 프록시 InvocationHandler

JDK 동적 프록시에 적용할 로직은 InvocationHandler 인터페이스를 구현해서 작성해야한다.
인수들은 다음과같다

  • Object proxy: 프록시 자신
  • Method method: 호출한 메서드
  • Object[] args : 메서드를 호출할 때 전달한 인이렇
    Proxy.newProxyInstance(로드할 클래스,어떤인터페이스기반으로 프록시사용할지, 프록시가 사용해야하는 로직)
    위와같이 세개의 인수를 넣어준다.
  • 해당 결과로 받은 프록시 객체를 빈으로 등록을 해서 사용할 수있다.
  • JDK동적프록시는 인터페이스가 필수이기때문에 인터페이스가 없을땐 사용할 수 없다.
  • 그럴때 사용하는 라이브러리가 CGLIB이다.

CGLIB

  • CGLIB : Code Generator Library
  • 바이트코드를 조작해서 동적으로 클래스를 생성하는 기술을 제공하는 라이브러리이다.
  • 인터페이스가 없어도 구체 클래스만 가지고 동적 프록시를 만들어낼 수 있다.
  • 원래 외부라리브러리인데 스프링에서 자체적으로 가지고 있다.
    ConcreteService target = new ConcreteService();

ConcreteService target = new ConcreteService();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ConcreteService.class);
enhancer.setCallback(new TimeMethodInterceptor(target));
ConcreteService proxy = (ConcreteService)enhancer.create();

- Enhancer : cglib는 해당 Enhancer를 사용해서 프록시를 생성한다.
- enhancer.setSuperclass(ConcreteService.class) : 구체 클래스를 상속 받아서 프록시를 생성할 수 있다. 어떤 쿠체클래스를 
상속받을지 지정한다.
- enhancer.setCallback(new TimeMethodInterceptor(target)): 프록시에 적용할 실행 로직을 할당한다.
- enhancer.create(): 프록시를 생성한다. 압서 설정한 setSuperclass에서 지정한 클래스를 상속 받아서 프록시가 만들어진다.

### CGLIB제약
- 클래스 기반 프록시는 상속을사용하기 때문에 몇가지 제약이 있다.
  - 부모클래스의 생성자를 체크해야한다. CGLIB는 자식 클래스를 동적으로 생성하기때문에 기본 생성자가 필요한다.
  - 클래스에 final키워드가 붙으면 상속이 불가능하다. 예외발생
  - 메서드에 final키워드가 붙으면 해당 메서드를 오버라이딩 할 수 없다.

'Springboot' 카테고리의 다른 글

빈 후처리기  (0) 2023.08.14
프록시 팩토리  (0) 2023.08.14
java리플렉션  (0) 2023.08.14
탬플릿 메서드 패턴  (0) 2023.08.14
Springboot/ ThreadLocal  (0) 2023.08.14