티스토리 뷰
간혹 커뮤니티 등에서 AOP 에 대한 얘기를 하면 많이들 잘 알고있는 내용이 이렇다.
"spring 에서는 인터페이스가 있으면 기본적으로 JDK 에서 제공하는 dynamic proxy 를 이용하고, 없으면 CGLIB 를 이용한 상속 기반 프록시를 구현해서 AOP 를 구현한다."
나도 머리로는 잘 이해하고 있긴한데 돌이켜 생각해보면 제가 작성하는 AOP 가 dynamic proxy 로 도는지, CGLIB 로 돌아가는지에 대해 크게 고민해본적이 없다. 그리고 더 곰곰히 생각해보면 dynamic proxy 로 돌아가는 AOP 를 본적이 거의 없다.
그리고 실제로 인터페이스를 구현하게 해서 AOP 를 사용하면 인터페이스가 있음에도 불구하고 CGLIB 로 도는걸 볼 수 있다!
(참고로 포스팅 작성 시점 기준 spring boot 2.4.5)
// 인터페이스를 이용한 Service 클래스에 AOP 를 걸었을때 구현 클래스 로그
AopServiceImpl$$EnhancerBySpringCGLIB$$cc5a6be3
알고있던 지식과는 좀 다른 방식으로 동작하는건데 왜 CGLIB 로 도는걸까? 이런저런 내용들을 보다가 EnableAspectJAutoProxy 애노테이션을 이용하면 될 것 같다.
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
javadoc 만 봐도 딱 이 애노테이션이 적절한것 같은데 이 애노테이션의 proxyTargetClass 를 false 로 설정해도 여전히 CGLIB 로 도는걸 볼 수 있다.
이 문제의 범인은 기본 설정에 있는데 spring boot 는 properties 를 통해 아래 두개의 속성을 지원하고 있다.
spring.aop.auto(default true)
spring.aop.proxy-target-class(default true)
spring.aop.auto 는 @EnableAspectJAutoProxy 를 자동으로 설정해주는 역할을 한다. default 값은 true 이기 때문에 따로 설정하지 않는 이상 @EnableAspectJAutoProxy 애노테이션은 항상 달려있다고 보면 된다. 그래서 우리가 추가로 달아줬던 @EnableAspectJAutoProxy 설정이 먹히지 않은 것이다.
해당 애노테이션은 AOP 를 위해 필요한 설정이므로 기본으로 달려있는게 좋은 것 같다. 더 문제는 아래있는 spring.aop.proxy-target-class 속성인데 이 속성은 이름만 봐도 알아챘겠지만 @EnableAspectJAutoProxy 애노테이션 안에 있는 proxyTargetClass 속성을 설정하게 된다. 그리고 default 값은 true 이다.
애노테이션 내부의 기본 값은 false 이지만 properties 를 통해 true 로 자동으로 변경하고 있던 것이다. spring.aop.auto 속성을 false 로 주게되면 애플리케이션 내부에 있는 @EnableAspectJAutoProxy 애노테이션 설정을 따라가게되므로 자연히 proxyTargetClass 값은 (따로 변경하지 않는다면) false 가 된다. 그게 아니면 spring.aop.proxy-target-class 속성만 false 로 변경해도 된다.
여튼 속성을 알맞게 설정한 후 코드를 돌려보면
// 인터페이스를 이용해 AOP 를 구현한 프록시 클래스 로그
com.sun.proxy.$Proxy74
// 인터페이스 없이 클래스만 이용해 AOP 를 구현한 프록시 클래스 로그
AopConcreteService$$EnhancerBySpringCGLIB$$4ba35e46
처음에 알고있던대로 인터페이스를 구현한 경우엔 dynamic proxy 를, 인터페이스가 없는 경우에는 CGLIB 를 이용한 것을 볼 수 있다.
참고로 JDK dynamic proxy 는 예전에 이런 포스팅을 작성한 적 있다.( multifrontgarden.tistory.com/228 )
'Java > spring' 카테고리의 다른 글
domain 에서 프레임워크 의존을 제거할 수 있을까 (4) | 2022.11.20 |
---|---|
TransactionTemplate 을 이용한 트랜잭션 제어 (0) | 2022.03.06 |
spring boot 2.4 에서 spring cloud config client 설정 (1) | 2021.04.11 |
spring boot 2.4 application.yaml 구동방식 변경 (1) | 2021.02.24 |
상속관계에서 Spring Transactional 애노테이션 동작 (0) | 2020.07.29 |
- Total
- Today
- Yesterday
- clean code
- spring cloud
- frontend개발환경
- TEST
- generics
- EffectiveJava
- Jackson
- Design Pattern
- db
- Git
- DesignPattern
- java
- Spring
- code
- JPA
- toby
- OOP
- frontcode
- MySQL
- JavaScript Core
- Kotlin
- backend개발환경
- java8
- mariadb
- servlet
- http
- go-core
- javascript
- programming
- 정규표현식
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |