Spring Framework

Spring Boot proxy-target-class 속성

Junuuu 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