자바의 정적 에이전트와 동적 에이전트를 깊이 있게 분석하다
1. 정적 에이전트: 프로그램이 실행되기 전에 프로그래머는proxy를 작성하고 컴파일해야 합니다. 즉, 프로그램이 실행되기 전에 에이전트 클래스의 바이트 파일이 생성됩니다.
피프록시류의 공공부류
package staticproxy;
public abstract class BaseClass {
public abstract void add();
}
피프록시류
package staticproxy;
public class A extends BaseClass {
public void add() {
System.out.println("A add !");
}
}
프록시류
package staticproxy;
public class Proxy {
BaseClass baseClass;
public void add() {
baseClass.add();
}
public void setBaseClass(BaseClass baseClass) {
this.baseClass = baseClass;
}
public static void main(String[] args) {
BaseClass baseClass = new A();
Proxy proxy = new Proxy();
proxy.setBaseClass(baseClass);
proxy.add();
}
}
2. 동적 프록시: 실제 코드는 컴파일하는 동안 생성되지 않고 운행하는 동안 반사 메커니즘을 활용하여 동적 생성피프록시 클래스 인터페이스
package jdkproxy;
public interface Service {
public void add();
public void update();
}
피프록시 클래스 A
package jdkproxy;
public class AService implements Service {
public void add() {
System.out.println("AService add>>>>>>>>>>>>>>>>>>");
}
public void update() {
System.out.println("AService update>>>>>>>>>>>>>>>");
}
}
피프록시 클래스 B
package jdkproxy;
public class BService implements Service {
public void add() {
System.out.println("BService add---------------");
}
public void update() {
System.out.println("BService update---------------");
}
}
테스트 클래스
package jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
MyInvocationHandler() {
super();
}
MyInvocationHandler(Object target) {
super();
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//
System.out.println("before-----------------------------");
//
Object result = method.invoke(target, args);
//
System.out.println("after------------------------------");
return result;
}
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
}
출력 결과: before---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------그 중에서 상기 빨간색 문장은 프록시 클래스를 만드는 관건적인 코드로 서비스 인터페이스에 부합되는 프록시 대상을 만들 수 있다. newProxy Instance라는 방법은 이런 일을 할 것이다. 그는 당신이 프록시할 모든 인터페이스를 코드가 동적으로 생성된 클래스로 실현할 것이다. 이 클래스의 모든 인터페이스 중의 방법은 InvocationHandler를 호출하는 것으로 다시 쓸 것이다.invoke () 메서드.
다음은 어떻게 대리 대상의 생성을 실현하는지 상세하게 소개한다.
Proxy의 new Proxy Instance 방법, 그 중에서 보기에 편리하도록 이 방법의 이상 처리 문장을 삭제했습니다
다음 public static Object new Proxy Instance(Class Loader loader, Class [] interfaces, Invocation Handlerh)throws
package jdkproxy;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Service aService = new AService();
MyInvocationHandler handler = new MyInvocationHandler(aService);
// Proxy InvocationHandler
Service aServiceProxy = (Service) Proxy.newProxyInstance(aService
.getClass().getClassLoader(), aService.getClass()
.getInterfaces(), handler);
// aServiceProxy , aServiceProxy Service
aServiceProxy.add();
System.out.println();
aServiceProxy.update();
// B
// Service bService = new BService();
// MyInvocationHandler handler = new MyInvocationHandler(bService);
// Service bServiceProxy = (Service) Proxy.newProxyInstance(bService
// .getClass().getClassLoader(), bService.getClass()
// .getInterfaces(), handler);
// bServiceProxy.add();
// System.out.println();
// bServiceProxy.update();
}
}
Proxy의 getProxy Class 방법
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) throws IllegalArgumentException
{
if (h == null) {
throw new NullPointerException();
}
//
Class cl = getProxyClass(loader, interfaces);
Constructor cons = cl.getConstructor(constructorParams);
// , MyInvocationHandler , MyInvocationHandler invoke , MyInvocationHandler
return (Object) cons.newInstance(new Object[] { h });
} getProxyClass
아래에서 Proxy Generator의generate Proxy Class 방법을 보십시오. 이 방법은 최종적으로 프록시 클래스의 바이트 파일을 생성합니다.
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException
{
// 、 、 ,
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces);
proxyClass = defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
proxyClasses.put(proxyClass, null);
return proxyClass;
}
그러면 최종적으로 생성된 프록시 클래스는 어떤 모습일까요?다음과 같다(equals,hashcode,toString 등 방법을 생략하고 구조 함수와add방법만 보여준다):
public static byte[] generateProxyClass(final String name, Class[] interfaces)
{
ProxyGenerator gen = new ProxyGenerator(name, interfaces);
//
final byte[] classFile = gen.generateClassFile();
// saveGeneratedFiles true,
if (saveGeneratedFiles) {
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
try {
FileOutputStream file =
new FileOutputStream(dotToSlash(name) + ".class");
file.write(classFile);
file.close();
return null;
} catch (IOException e) {
throw new InternalError(
"I/O exception saving generated file: " + e);
}
}
});
}
//
return classFile;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.