讨论和学习JDK API 实现动态代理,源码分析
动态代理
:为实现某个接口的原始类(被代理类),在运行时动态生成代理对象
代理
:在被代理之前的,代理被代理的
被代理
:需要代理协助的对象
1.代理
和被代理
之间要有关联
2.对外展示的功能是一样。
3.再想想具体的Java实现
通过什么手段能为一个类或者接口动态生成代理 ?
类
是由属性
和方法
构成,这里重点关注方法,那我们我们生成的类,应该具备哪些方法呢? 因为代理和被代理对外是一致的,所被代理
有哪些方法,那代理
也就有哪些方法,所以我们就可以生成类,接着就可以生成代理对象。接口
public interface ITest {
void test();
}
被代理实现接口
/**
* 被代理
* @Author: malone
* @Date 2020/6/26 23:08
*/
public class Represented implements ITest {
@Override
public void test() {
System.out.println("Represented method invocation");
}
}
InvocationHandler
接口/**
* @Author: malone
* @Date 2020/6/26 23:09
*/
public class DynamicInvocationHandler implements InvocationHandler {
// 被代理对象
private Object object;
public DynamicInvocationHandler(Object object){
this.object = object;
}
// 方法调用拦截
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("invoke proxy method");
method.invoke(object,args); // 调用被代理方法,通过反射方法
return null;
}
}
public static Object newProxyInstance()
创建代理对象public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
loader
:当前被代理对象使用的类加载器
interfaces
:需要实现接口数组
h
: 第2步实现了InvocationHandler
接口的对象
下面是动态代理DynamicProxy
的测试,通过newProxyInstance
方法,创建代理对象proxy
,在代理
对象上调用和被代理
对象相同的方法,我们看到,代理对象和被代理对象的信息都输出了。
/**
* @Author: malone
* @Date 2020/6/26 23:11
*/
public class DynamicProxyTest {
public static void main(String[] args) {
String property = "sun.misc.ProxyGenerator.saveGeneratedFiles";
System.getProperties().setProperty(property ,"true");
// 以上两句话用于保存,JDK动态产生的代理类Proxy0
ITest represented = new Represented(); // 被代理实例
ITest proxy = (ITest)Proxy.newProxyInstance(represented.getClass().getClassLoader(),
represented.getClass().getInterfaces(),new DynamicInvocationHandler(represented));
proxy.test(); // 通过代理调用方法
}
}
下面是输出
invoke proxy method
Represented method invocation
String property = "sun.misc.ProxyGenerator.saveGeneratedFiles";
System.getProperties().setProperty(property ,"true");
上面两个代码将保存生成的代理类$Proxy0
到本地.我,我们打开看看。
public final class $Proxy0 extends Proxy implements ITest {
生成的类继承了Proxy类,实现了ITest类,这也就保证了和被代理一致的行为。至于继承Proxy类是为了调用InvocationHandler中的Invoke方法,也就是我们实现代理逻辑的方法。如下所示,我们主要看ITest中定义的方法test在生成类中的实现。
public final void test() throws {
try {
// 调用父类Proxy中的InvocationHandler的invoke方法
super.h.invoke(this, m3, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
代理
对象和被代理
对象两个角色InvocationHandler
接口实现)、代理的创建Proxy.newProxyInstance
方法的调用反射
知识:被代理类的方法调用