动态代理是提供一种抽象,将对实例的不同方法的调用重定向到一个统一的处理函数,然后做自定义的逻辑处理,整个过程对于调用者是透明的,并且代理类与业务无关。
被代理的类可以不在本地,动态代理语法提供一种抽象方式,被代理的类可以位于远程主机,这就是RPC框架的实现原理。
一、RPC框架中动态代理的职责
RPC框架需要像调用本地接口一样调用远程接口,也就是上文提到面临的那三个问题。如何组装数据报文,通过网络发送到服务提供方,屏蔽远程接口调用的细节,这就需要通过动态代理来实现。
二、动态代理实现方式
- jdk动态代理
- cglib动态代理
- javassist动态代理
- ASM字节码
- javassist字节码
其中,Spring使用的是jdk和cglib的动态代理,Dubbo默认使用的是javassist动态代理。
三、JDK动态代理
JDK的动态代理只能对接口进行代理。这是因为Java的单继承造成的,JDK生成的动态代理类需要继承java.lang.reflect.Proxy,所以要求只能对接口代理。Spring中是使用JDK动态代理对接口代理,对类代理使用cglib。
JDK动态代理角色
代理接口
JDK动态代理机制规定给调用者使用的代理类只能是接口1
2
3interface Operation {
int add(int a, int b);
}代理处理器
统一的处理函数,JDK动态代理约定要实现InvocationHandler接口。1
2
3
4
5
6
7
8
9
10
11
12
13class OperationProxyHandler implements InvocationHandler {
private Object target;//被代理对象
// 构造方法保持被代理对象
public OperationProxyHandler(Object target){
this.target = target;
}
// 统一处理函数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//使用反射将放到代理到被代理对象上
return method.invode(target, args)
}
}被代理类
实际执行工作的类1
2
3
4
5
6class OperationImpl implements Operation {
public int add (int a, int b) {
return a + b;
}
}创建代理类
调用者使用的是实现代理接口的代理类,代理类的创建,JDK的动态代理也有相应的api供我们使用1
2
3
4
5
6public static void main(String[] args) {
Operation op = (Operation) Proxy.newProxyInstance(Operation.class.getClassLoader(), // 加载接口的类加载器
new Class[]{Operation.class}, // 一组接口
new MyInvocationHandler(new OperationImpl())); // 自定义的InvocationHandler,持有实现类实例
System.out.println(op.add(2, 3));
}
四、总结
JDK动态代理是实现RPC的基础,这里我们了解JDK的动态代理的使用,Dubbo默认是使用javassist动态代理,但都是使用动态代理来实现远程方法调用,只是实现动态代理的方式不同。