静态代理
public class TargetClass{void method1()
}
public class ProxyClass{
private TargetClass target;
public void method1(){target.method1()
}
}
- 代理类持有目标类的引用
动态代理
public interface TargetIntf{void method1();
}
public DynamicProxy implements InvocationHandler{
@Override
public Object invoke(Object o, Method method, Object[] args){//do proxy}
}
InvocationHandler handler = new DynamicProxy();
Proxy theProxy = (TargetIntf)Proxy.newInstance(hander.getClass().getClassLoader(), new Class[]{TargetIntf.class}, handler);
theProxy.method1()
- 要有接口
- 要实现 InocationHandler
- 通过 Proxy.newInstance 来生成代理类
- 通过强转取得目标类的实例
如何理解动态代理
当调用 theProxy 的 method1 时,会触发 handler.invoke 方法的调用,方法 (Method) 和参数都会传递给 invoke 方法,invoke 方法里面想做什么都行。
为什么 Proxy.newInstance 可以强转成 TargetIntf 呢?
Proxy.newInstance 返回的对象实现了 TargetIntf 接口的方法,所以可以强转。
为什么调用 proxy 的 method1 方法会调用到 handler 的 invoke 方法?
Proxy.newInstance 返回的对象组合了 handler,并在 method1 方法的实现逻辑中添加了 handler.invoke 的调用。
Proxy.newInstance 如何动态的实现 TargetIntf 的方法并返回对象实例呢?
动态的生成 class 文件,java 类的信息都是从 class 文件加载进来的,Proxy.newInstance 方法中动态的生成了 class 文件并加载。
动态代理能干嘛?
- 提供了另外一种实现接口的方式,不用 implements 也能实现接口。
- 可以用来写框架
试想一下,如果没有动态代理,dubbo 框架如何实现?
动态代理的 dubbo 实现:
- client 和 server 端都依赖 api 的接口
- client 端不实现 api 接口,通过动态代理,把 api 接口调用连接到 Invocation.invoke 方法上,在此方法中将对象、方法名、参数等通过网络发送给 server 端
- server 端实现 api 的接口,把 client 端发送过来的 rpc 调用连接到 api 接口的具体实现上。
没有动态代理的实现:
- client 和 server 端都依赖 api 接口
- client 端实现 api 接口,接口的实现逻辑为把对象、方法名、参数等通过网络发送给 server 端
- server 端实现 api 的接口,把 client 端发送过来的 rpc 调用连接到 api 接口的具体实现上。
有了动态代理,dubbo rpc 中的网络交互部分可以完全写在 dubbo 框架中,对用户来说编程更加方便。
没有动态代理,client 端的 api 实现代码也可以通过工具自动生成,不过这样让框架使用起来更加的复杂。