实现
JDK动态代理大致分为三个步骤:
- 定义代理接口
- 定义代理接口实现类
- 定义动态代理调用处理器
定义
package com.example.demo.java.proxy;
/**
* 代理接口
*/
public interface Subject {
String sayHello();
}
package com.example.demo.java.proxy;
/**
* 代理接口实现类
*/
public class SubjectImpl implements Subject {
@Override
public String sayHello() {
System.out.println("hello");
return "success";
}
}
package com.example.demo.java.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* 动态代理调用处理器
*/
public class ProxyInvocationHandler implements InvocationHandler {
/**
* 代理类中的真实对象
*/
private Object target;
public ProxyInvocationHandler(Object target) {
this.target = target;
}
/**
* @param proxy 代理类代理的真实代理对象com.sun.proxy.$Proxy0
* @param method 我们所要调用某个对象真实的方法的Method对象
* @param args 指代代理对象方法传递的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before");
Object invoke = method.invoke(target, args);
System.out.println("after");
return invoke;
}
}
调用
- 创建被代理接口的实现类
- 创建动态代理类,说一下三个参数
- 类加载器
- 被代理类所实现的接口数组
- 调用处理器(调用被代理类方法,每次都经过它)
- 被代理实现类调用方法
package com.example.demo.java.proxy;
import java.lang.reflect.Proxy;
public class JDKProxyDemo {
public static void main(String[] args) {
// 保存动态代理生成的类文件 设置为true,运行之后即可在本地查看
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
Subject subject = new SubjectImpl();
/**
* 通过Proxy类的newProxyInstance方法创建代理对象
* 参数
* 第一个参数:subject.getClass().getClassLoader(),使用subject对象的classloader对象来加载我们的代理对象
* 第二个参数:subject.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
* 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
*/
Subject proxy = (Subject) Proxy
.newProxyInstance(
subject.getClass().getClassLoader(),
subject.getClass().getInterfaces(),
new ProxyInvocationHandler(subject)
);
System.out.println("return: " + proxy.sayHello());
}
}
执行代码可以看到
生成了一个$Proxy动态代理对象
动态代理对象
生成的动态代理对象类文件
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.sun.proxy;
import com.example.demo.java.proxy.Subject;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
// 继承 Proxy
// 实现 Subject 接口
public final class $Proxy0 extends Proxy implements Subject {
private static Method m1;
private static Method m3;
private static Method m2;
private static Method m0;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
public final boolean equals(Object var1) throws {
try {
// 动态代理的方法通过invoke代理
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String sayHello() throws {
try {
return (String)super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m3 = Class.forName("com.example.demo.java.proxy.Subject").getMethod("sayHello");
m2 = Class.forName("java.lang.Object").getMethod("toString");
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
}