728x90
반응형
JDK Proxy
- 인터페이스 기반으로 프록시를 동적으로 만든다.
- 즉 인터페이스가 있어야 프록시를 만들수 있다.
JDK Proxy 예제
- JDK 동적 프록시를 만들기 위해서는 InvoctionHandler 를 구현해주면 된다.
package java.lang.reflect;
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
- proxy: 프록시 자신
- method: 호출한 메소드
- args: 메소드를 호출할때 전달한 인수
UserServiceInterface
- 앞서 말했듯이 JDK proxy 는 인터페이스가 필요하다.
package com.example.exercise.aop.jdk;
public interface UserServiceInterface {
public void save();
}
UserServiceImpl
package com.example.exercise.aop.jdk;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class UserServiceImpl implements UserServiceInterface {
@Override
public void save() {
log.info("save user info");
}
}
LogInvocationHandler
package com.example.exercise.aop.jdk;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
@Slf4j
public class LogInvocationHandler implements InvocationHandler {
private final Object target;
public LogInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("실행 전 로그");
Object result = method.invoke(target, args);
log.info("실행 후 로그");
return result;
}
}
- Object target 은 외부에서 받는 타겟 클래스이다.
- Object result = method.invoke(target, args);
- 리플렉션을 이용하여 target 의 메소드를 수행한다.
TestCode
package com.example.exercise.aop;
import com.example.exercise.aop.jdk.LogInvocationHandler;
import com.example.exercise.aop.jdk.UserServiceInterface;
import com.example.exercise.aop.jdk.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Proxy;
@Slf4j
class LogInvocationHandlerTest {
@Test
void LogTest () {
UserServiceInterface target = new UserServiceImpl();
LogInvocationHandler logInvocationHandler = new LogInvocationHandler(target);
UserServiceInterface proxy = (UserServiceInterface) Proxy.newProxyInstance(UserServiceInterface.class.getClassLoader(), new Class[]{UserServiceInterface.class}, logInvocationHandler);
proxy.save();
log.info("target class = {}", target.getClass());
log.info("proxy class = {}", proxy.getClass());
}
}
- Proxy.newProxyInstance(classLoader, interface array, handler logic);
- 클래스로더정보, 인터페이스, 핸들러 로직을 넣어주면 된다.
- 그러면 해당 인터페이스로 동적 프록시를 생성하고 그결과를 반환한다.
결과
- proxy class = 를 보면 jdk proxy 가 만들어진것을 확인 할 수 있다.
18:51:33.903 [Test worker] INFO com.example.exercise.aop.jdk.LogInvocationHandler -- 실행 전 로그
18:51:33.906 [Test worker] INFO com.example.exercise.aop.jdk.UserServiceImpl -- save user info
18:51:33.906 [Test worker] INFO com.example.exercise.aop.jdk.LogInvocationHandler -- 실행 후 로그
18:51:33.906 [Test worker] INFO com.example.exercise.aop.LogInvocationHandlerTest -- target class = class com.example.exercise.aop.jdk.UserServiceImpl
18:51:33.907 [Test worker] INFO com.example.exercise.aop.LogInvocationHandlerTest -- proxy class = class jdk.proxy3.$Proxy11
JDK 동작 과정
- client 가 서비스를 직접 호출 하지 않고
- 프록시를 호출 하여 실제 서비스를 호출하게 된다.
참고:
728x90
반응형
'Spring > Spring 고급' 카테고리의 다른 글
[Spring] Spring AOP 개념 (0) | 2023.06.27 |
---|---|
[Spring] AOP 개념 (0) | 2023.06.15 |
[Spring] CGLIB (0) | 2023.04.18 |
[Spring] Proxy (0) | 2023.01.23 |
댓글