| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 개발자
- 인덱스
- 레드마인
- 일감관리
- It
- spring aop
- frontend
- 오라클
- 웹프론트
- PreparedStatement
- 백엔드
- 스프링
- Si
- db
- 이슈관리
- java
- kibana
- AOP
- redmine
- 자바
- Database
- 데이터베이스
- 비전공개발자
- backend
- 검색
- PM
- elasticsearch
- 엘라스틱서치
- 프로젝트관리
- spring
- Today
- Total
리타의 저장소
Spring AOP | CGLIB Proxy 본문


CGLIB Proxy
CGLIB Proxy는 JDK Dynamic Proxy와 다르게 바이트코드 조작(ASM 기반)으로 대상 클래스의 서브클래스를 만들어 프록시를 구현한다.
JDK Proxy가 원본 객체가 구현한 Interface에 대한 Proxy를 만들어준다면, CGLIB Proxy는 직접 Class를 상속받아서 Override하는 방식으로 Proxy를 만들어주게 된다. 그래서 interface가 없는 클래스라도 Proxy를 생성할 수 있다.
예를들어, ProxyService 라는 Interface를 구현한 ProxyServiceImpl이 있다면, CGLIB로 Proxy를 구현할 떄 ProxyService라는 interface가 아닌 구체 구현 클래스를 상속받는 식으로 구현된다.
public class ProxyServiceImpl implements ProxyService {
...
}
public class CGLIBProxyService extends ProxyServiceImpl {
...
}
조금 더 자세히 살펴보자면,
CGLIB Proxy의 경우 , 런타임에 Enhancer가 대상 클래스를 상속한 프록시 클래스를 만들고, 메서드 호출을 MethodInterceptor#intercept() 로 가로채서 공통 로직(로깅/트랜잭션/보안 등) 을 실행한 뒤 MethodProxy#invokeSuper()로 원본 로직을 호출한다.
Enhancer e = new Enhancer();
e.setSuperclass(Target.class); // Super Class
e.setCallback((MethodInterceptor) (obj, method, args, proxy) -> {
// 전/후 처리
Object ret = proxy.invokeSuper(obj, args);
return ret;
}); // InvocationHandler 와 동일한 역할
Target proxy = (Target) e.create();
MethodInterceptor 는 InvocationHandler와 동일한 의미를 갖는다. 실제 코드를 까보면, intercept라는 단 하나의 Method 만 갖는 interface라는 것을 확인할 수 있다. 파라미터로는 해당 Method에 대한 정보를 받는다.
MethodInterceptor
package net.sf.cglib.proxy;
public interface MethodInterceptor extends Callback
{
/**
* All generated proxied methods call this method instead of the original method.
* The original method may either be invoked by normal reflection using the Method object,
* or by using the MethodProxy (faster).
* @param obj "this", the enhanced object
* @param method intercepted Method
* @param args argument array; primitive types are wrapped
* @param proxy used to invoke super (non-intercepted method); may be called
* as many times as needed
* @throws Throwable any exception may be thrown; if so, super method will not be invoked
* @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
* @see MethodProxy
*/
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
MethodProxy proxy) throws Throwable;
}
All generated proxied methods call this method instead of the original method.
“모든 프록시 메서드는 원본 대신 MethodInterceptor를 호출 해야한다.” 라고 안내되어있다.
위에서도 설명했듯, CGLIB는 대상 클래스 (Target Class)를 상속해서 Subclass(서브클래스를 런타임에 생성한다. 그리고 원본 메서드를 오버라이드 한 뒤, 그 오버라이드 된 메서드 안에서 직접 원본 로직을 실행하지 않고, MethodInterceptor#intercept()를 호출하게 만들기 때문이다.
여하튼, Enhancer는 구체 클래스를 상속 받고, interceptor에서 작성된 대로 수행하는 Proxy Instance를 만들어준다.
JDK Proxy와의 가장 큰 차이점은, JDK Proxy의 경우 Reflection API를 이용해 InvocationHandler에서 작성된 내용을 수행하는 것이고,
이쯤에서 잠깐 확인하는 JDK Proxy 호출 흐름
Client
│
▼
proxyInstance.someMethod(args)
│
▼
(프록시 클래스 내부 구현: 동적으로 생성된 인터페이스 구현체)
│
▼
InvocationHandler.invoke(proxy, Method, args) ← ← ← ← ← ← ← ← ← ← ←
│ (리플렉션 기반 호출)
▼
target.method(args)
│
▼
실제 비즈니스 로직 실행
CGLib는 처음 한번만 바이트코드를 조작해서 Proxy 객체를 생성하고, 그 클래스 안의 오버라이드된 메서드가 직접 MethodInterceptor.intercept()를 호출한다 (직접 호출).
→ 이후, intercept() 안에서 super.method()를 직접 호출한다. 메서드 실행이 생성된 프록시 클래스 내부에서 이루어짐.
CGLIB Proxy 호출 흐름
Client
│
▼
proxyInstance.someMethod(args)
│
▼
(overridden method in subclass)
│
▼
MethodInterceptor.intercept(this, Method, args, MethodProxy)
│
▼
MethodProxy.invokeSuper(this, args)
│
▼
super.someMethod(args) → 즉, 원본 클래스의 메서드 직접 호출
│
▼
실제 비즈니스 로직 실행
* JDK Proxy도 프록시 클래스를 한 번 생성하긴 한다. 메서드 호출 경로의 차이임. reflection을 통하냐, 직접 호출이냐의 문제. (인터페이스 기반 AOP냐, 클래스 기반 AOP냐)
'Dev > Backend' 카테고리의 다른 글
| Spring AOP | @Transactional과 self-invocation 문제 (0) | 2025.10.11 |
|---|---|
| Spring AOP | 돌고돌아 JDK Dynamic Proxy vs CGLIB Proxy (0) | 2025.10.11 |
| Spring AOP | JDK Dynamic Proxy (0) | 2025.10.11 |
| Spring AOP | JDK Dynamic Proxy & CGLIB Proxy (0) | 2025.10.11 |
| Spring AOP | Spring AOP 주요 개념 요약 (0) | 2025.10.11 |