AOP 프록시 기술과 한계 - 타입 캐스팅

박찬우·2024년 2월 17일
0

스프링

목록 보기
80/88

타입 캐스팅

  • JDK 동적 프록시는 인터페이스가 필수이고, 인터페이스를 기반으로 프록시를 생성한다.
  • CGLIB는 구체 클래스를 기반으로 프록시를 생성한다
  • 인터페이스가 없고 구체 클래스만 있는 경우에는 CGLIB를 사용해야 한다. 그런데 인터페이스가 있는 경우에는 JDK 동적 프록시나 CGLIB 둘중에 하나를 선택할 수 있다.
  • 스프링이 프록시를 만들때 제공하는 ProxyFactory 에 proxyTargetClass 옵션에 따라 둘중 하나를 선택해서 프록시를 만들 수 있다
    • proxyTargetClass=false JDK 동적 프록시를 사용해서 인터페이스 기반 프록시 생성
    • proxyTargetClass=true CGLIB를 사용해서 구체 클래스 기반 프록시 생성
    • 참고로 옵션과 무관하게 인터페이스가 없으면 JDK 동적 프록시를 적용할 수 없으므로 CGLIB를 사용한다

JDK 동적 프록시


  • JDK Proxy는 MemberService 인터페이스를 기반으로 생성된 프록시이다. 따라서 JDK Proxy는 MemberService 로 캐스팅은 가능하지만 MemberServiceImpl 이 어떤 것인지 전혀 알지 못한다
    @Test
    void jdkProxy() {
        MemberServiceImpl target = new MemberServiceImpl();
        ProxyFactory proxyFactory = new ProxyFactory(target);
        proxyFactory.setProxyTargetClass(false); // JDK 동적 프록시

        // 인터페이스로 캐스팅 성공
        MemberService proxy = (MemberService) proxyFactory.getProxy();

        // 구현 클래스로 캐스팅 시도 실패 ClassCastException 예외 발생
        Assertions.assertThrows(ClassCastException.class, () -> {
            MemberServiceImpl castingMemberService = (MemberServiceImpl) proxy;
        });
    }

CGLIB


  • CGLIB Proxy는 MemberServiceImpl 구체 클래스를 기반으로 생성된 프록시이다. 따라서 CGLIB Proxy는 MemberServiceImpl 은 물론이고, MemberServiceImpl 이 구현한 인터페이스인 MemberService 로도 캐스팅 할 수 있다
    @Test
    void cglibProxy() {
        MemberServiceImpl target = new MemberServiceImpl();
        ProxyFactory proxyFactory = new ProxyFactory(target);
        proxyFactory.setProxyTargetClass(true); // CGLIB 프록시

        // 인터페이스로 캐스팅 성공
        MemberService proxy = (MemberService) proxyFactory.getProxy();

        // 구현 클래스로 캐스팅 시도 성공
        MemberServiceImpl castingMemberService = (MemberServiceImpl) proxy;
    }
profile
진짜 개발자가 되어보자

0개의 댓글