动态代理源码解析
什么是代理模式
代理模式即 Proxy Pattern。代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
文章图片
image.png jdk动态代理demo
public interface Interview {
String result();
}
public class InterviewImpl implementsInterview {
@Override
public String result() {
System.out.println("真正想要面试的人。");
return "ok";
}
}
public class ProxyHandler implements InvocationHandler {
private InterviewImpl interview;
public ProxyHandler(InterviewImpl interview) {
this.interview = interview;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("准备面试");
Object invoke = method.invoke(interview, args);
System.out.println("准备结束");
return invoke;
}
public static void main(String[] args) {
//会在项目的根目录生成com.sun.proxy生成$parxo0.class
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
InterviewImpl interview = new InterviewImpl();
//这里也可以使用Proxy.getProxyClass().getConstructor()获取代理对象
//这里获取的是被代理对象,并不是目标对象
Interview o = (Interview) Proxy.newProxyInstance(ProxyHandler.class.getClassLoader(), new Class[]{Interview.class},new ProxyHandler(interview));
String result = o.result();
}
}
从上面这个demo我们可以看出,只是直接调用面试对象,而是通过动态代理调用面试对象。
生成的代理对象 【动态代理源码解析】我们可以看出生成代理对象类名是$Proxy+数字
代理对象代理了接口本身的方法,同时也代理啦toString(),equals(),hashcode()。
public final class $Proxy0 extends Proxy implements Interview {
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 {
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 result() 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.amos.study.base.java.proxy.dynamic.Interview").getMethod("result");
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());
}
}
}
JDK动态代理源码解析
我真的不知道改怎么去描述代码。首先调用getProxyClass0(loader, intfs)得到代理类。线程proxyClassCache缓存中获取,不存在则创建Factory,从Factory中组装代理对象,代理对象的包名com.sun.proxy+$Proxy+AtomicLong。然后通过 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); 生成字节码。调用defineClass0()将字节码写入类文件中。cl.getConstructor(constructorParams)返回带有实现InvocationHandler接口的构造器。其实这里就找到了代理类。jdk代理是生成一个代理接口的代理类。
推荐阅读
- 事件代理
- Android事件传递源码分析
- Quartz|Quartz 源码解析(四) —— QuartzScheduler和Listener事件监听
- 动态组件与v-once指令
- 设计模式-代理模式-Proxy
- [源码解析]|[源码解析] NVIDIA HugeCTR,GPU版本参数服务器---(3)
- ffmpeg源码分析01(结构体)
- Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!
- Vue源码分析—响应式原理(二)
- java静态代理模式