ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Boot proxy-target-class 속성
    Spring Framework 2023. 11. 10. 00:01

    개요

    관례적으로 클래스를 인터페이스로 구현하는 이유에 대해 찾아보게 되었고 이후 proxy-target-class라는 것을 알게 되었습니다.

    따라서 해당 설정을 실험해보고자 합니다.

     

     

    application.yml

    spring:
      aop:
        proxy-target-class: false

    기본값이 true입니다.

    해당값을 false로 바꾸면 어떤 일이 일어날까요?

     

    • false - Jdk Dynamic Proxy를 사용한다는 의미로 인터페이스로 구현되어 있지 않다면 AOP가 적용되지 않음!
    • true - CGLIB가 대상 클래스를 상속받아 프락시를 구현해서 인터페이스가 없어도 된다, 클래스가 final인 경우 프락시 생성이 불가능하다.

     

    proxy-target-class 속성이란?

    "description": "Whether subclass-based (CGLIB) proxies are to be created (true)
    , as opposed to standard Java interface-based proxies (false).",

    proxy-target-class 속성을 타고 들어가 보면 spring-boot-autuconfigure 모듈의 spring-configuration-metadata.json 파일에 위와 같은 설명이 적혀있습니다.

     

    true인 경우 CGLIB 방식으로 proxy가 생성되고, 반대인 경우에는 자바의 interface 방식으로 적용된다고 합니다.

     

    테스트

    proxy-target-class : true인 경우에는 해당 클래스가 인터페이스로 구현되었는지 유무에 관계없이 CGLIB 방식의 Proxy가 적용됩니다.

     

     

    Consider injecting the bean as one of its interfaces or forcing the use of CGLib-based proxies
    by setting proxyTargetClass=true on @EnableAsync and/or @EnableCaching.

    proxy-target-class : false인 경우에는 타깃 클래스가 인터페이스로 구현되어 있지 않은 경우에 예외가 발생합니다.

     

     

    proxy-target-class: false이며 Injecting을 하는 부분을 구체 클래스가 아닌 interface로 주입받으면 JdkDynamicAopProxy 방식이 적용된 것을 알 수 있습니다.

     

    Spring Boot에서 CGLIB가 기본전략인 이유

    • final이 붙으면 오버라이딩이 불가능하므로 CGLIB프록시가 작동하지 않는다.
    • Enhancer의존성을 추가해야 한다.
      • 3.2 version Spring core 패키지에 포함되어서 의존성 추가하지 않아도 된다.
    • Default 생성자가 필요하다.
      • 4.0 version Objensis 라이브러리를 포함하면서 필요 없어졌다.
    • 타깃의 생성자를 두 번 호출한다.
      • 4.0 version Objensis 라이브러리를 포함하면서 한 번만 호출된다.

    스프링부트 총 책임자 Phill

     

    인터페이스 기반 프락시는 때때로 ClassCast Exceptions를 추적하기 어렵게 한다. 특히, @Bean이 JDK 프락시로 대체되어 원래 클래스 형식으로 주입되지 않을 수 있었다.

    스프링 프레임워크는 요즘 CGLIB의 음영 복사가 있기 때문에, 즉시 사용하지 않을 이유가 거의 없었다.

     

    마무리

    만약 특정 이유에 따라 proxy-target-class가 fasle로 설정해야 하거나, 기본전략이 JdkDynamicProxy 방식이라면 클래스에 인터페이스를 구현하고 인터페이스로 빈을 주입해야 하는 상황이 있을 수 있습니다.

     

     

     

     

     

     

    참고자료

    https://giron.tistory.com/129

    https://wonwoo.me/m/277

     

    댓글

Designed by Tistory.