반응형
특징
- 인터페이스 기반으로 만들기 때문에 인터페이스가 필수
- 런타임에 동적으로 프록시 객체를 만들어줌
사용 예시
public static void main(String[] args) {
TestInterface ref = (TestInterface) Proxy.newProxyInstance(
TestInterface.class.getClassLoader(),
new Class[]{TestInterface.class}, handler);
ref.call();
}
}
Proxy.newProxyInstance
- 동적 프록시 생성 함수
- 인자 값
- 프록시 인터페이스의 클래스 로더
- 인터페이스 클래스에 대한 배열 입력
- 프록시 동작을 수행하기 위한 InvocationHandler
인터페이스만으로 프록시를 사용할 수 있을까?
구현 코드
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface TestInterface {
void call();
}
public class JdkDynamicProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object result = method.invoke(args); // 호출
System.out.println("after invoke");
return result;
}
public static void main(String[] args) {
JdkDynamicProxy handler = new JdkDynamicProxy(); // 구현체 미사용
TestInterface ref = (TestInterface) Proxy.newProxyInstance(
TestInterface.class.getClassLoader(),
new Class[]{TestInterface.class}, handler); // 인터페이스만 선언
ref.call(); // 인터페이스의 메서드가 호출된다
}
}
결과
- 구현체 없이 인터페이스만 가지고 동적 프록시를 생성했을 때, 아래와 같은 에러 발생
- 에러가 발생한 이유는 컴파일 에러를 피하기 위해 파라미터를 하나만 넣어줬는데, invoke 메서드 내부에서 Object가 null이기 때문에 클래스를 가져올 수 없다는 것
구현체 선언의 두 가지 방법
동적 프록시를 생성할 때 선언
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface TestInterface {
void call();
}
public class JdkDynamicProxy implements InvocationHandler {
private final Object target;
public JdkDynamicProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object result = method.invoke(target, args);
System.out.println("after invoke");
return result;
}
public static void main(String[] args) {
JdkDynamicProxy handler = new JdkDynamicProxy(
(TestInterface) () -> System.out.println("This is Implementation"));
TestInterface ref = (TestInterface) Proxy.newProxyInstance(
TestInterface.class.getClassLoader(),
new Class[]{TestInterface.class}, handler);
ref.call();
}
}
invoke 메서드를 호출할 때 선언
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface TestInterface {
void call();
}
public class JdkDynamicProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before invoke");
Object result = method.invoke((TestInterface) () -> System.out.println("This is Implementation"), args);
System.out.println("after invoke");
return result;
}
public static void main(String[] args) {
JdkDynamicProxy handler = new JdkDynamicProxy();
TestInterface ref = (TestInterface) Proxy.newProxyInstance(
TestInterface.class.getClassLoader(),
new Class[]{TestInterface.class}, handler);
ref.call();
}
}
Method.invoke의 파라미터로 뭘 넣어야해요..??
- - invoke의 첫 번째 파라미터는 구현체 정보를 넣어야한다.
동적 프록시는 언제 사용하는걸까?
- DB 트랜잭션 관리
- 유닛 테스트를 위한 동적 Mock 객체
- DI Container
- AOP
반응형
LIST
'언어 > java' 카테고리의 다른 글
[시스템 프로그래밍] JVM 실행 흐름에 대한 코드 분석 (0) | 2024.07.17 |
---|---|
JDK21 Update 정리 (2) | 2023.11.22 |
[Java] 자바의 컬렉션(Collection) (0) | 2020.05.10 |
JAVA EE,SE,ME에 대하여 (0) | 2019.08.08 |
JDK와 JRE (0) | 2019.08.08 |