您的位置:首页 > 其它

服务治理中间件 Dubbo 原理解析(代理)读书笔记

2018-08-23 16:42 295 查看
[code]代理模式这里不再逻辑介绍, dubbo 中有使用这种模式,如: dubbo 服务的消费
端获取的就是对远程服务的一个代理。 Dubbo 由代理工厂 ProxyFactory 对象创
建代理对象
一: ProxyFactory 的接口定义
@SPI("javassist")
public interface ProxyFactory {

@Adaptive({Constants.PROXY_KEY})
<T> T getProxy(Invoker<T> invoker) throws RpcException;

@Adaptive({Constants.PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
1. @SPI 指定默认使用 javassist 字节码技术来生成代理对象
2. 接口定义了生成代理对象的方法 getProxy, 入参是 invoker 对象
3. 接口定义了获取 invoker 对象, invoker 对象是个可执行对象,这里 inovker
对象的 invoke 方法其实执行的是根据 url 获取的方法对第一个入参的实体对
象的调用,即:如果 url 的得知调用方法 sayHello, 入参 proxy 为空 Test
对象实现 test,那 invoker.invoke()就是 test.sayHello()

AbstractProxyFactory: 代理工厂的公共抽象, 这里抽象实现主要是获取需要
代理的接口,代理接口可以在设置在 url 中 key 为 interfaces, 如果是多个接
口用逗号分隔, 如果没有在 url 中指定,代理 invoker 获取的和 EchoService接口
JdkProxyFactory: 利用 jdk 动态代理来创建代理,实现来说比较简单
JDK 动态代理获取代理对象
public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T)
Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces,
new InvokerInvocationHandler(invoker));
}
InvokerInvocationHandler 是 jdk 动态代理创建一定要构建的参数,这里它的invoke 方法只是简单的调用了 invoker.invoke 方法, Invoker 在 dubbo 中代表一个可执行体,一切都向它靠拢。
获取 invoker 对象
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes, Object[] arguments) throws Throwable {
Method method = proxy.getClass().getMethod(methodName,parameterTypes);
return method.invoke(proxy, arguments);
}
};
}
这里创建的 Invoker对象,执行invoke方法,其实就是利用反射利用入参执行对应对象的对应方法。

二: Javassist 字节码技术生成代理
JavassistProxyFactory: 利用字节码技术来创建对象
public <T> T getProxy(Invoker<T> invoker,Class<?>[] interfaces) {
return(T)Proxy.getProxy(interfaces).newInstance(newInvokerInvocationHndler(invoker));
}
看似跟 jdk 生成代理一样, 其实这里的 Proxy 类不是 jdk 中自带那个生成代理
对象的类是 com.alibaba.dubbo.common.bytecode.Proxy。
这个 dubbo 自己写的 Proxy 类,利用要代理的接口利用 javassist 工具生成代理
代码获取 Invoker 对象
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
final Wrapper wrapper =Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0
? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
protected Object doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName,parameterTypes, arguments);
}
};
}
根据传入的 proxy 对象的类信息创建对它的包装对象 Wrapper
返回 Invoker 对象实例, 这个 invoker 对象 invoke 方法可以根据传入的
invocation 对象中包含的方法名,方法参数来调用 proxy 对象返回调用结果
com.alibaba.dubbo.common.bytecode.Proxy 生成代理对象的工具类
1. 遍历所有入参接口,以;分割连接起来,以它为 key 以 map 为缓存查找如果
有,说明代理对象已创建返回
2. 利用 AtomicLong 对象自增获取一个 long 数组来作为生产类的后缀,防止冲突
3. 遍历接口获取所有定义的方法,加入到一个集合 Set<String> worked 中 ,
用来判重,获取方法 y 应该在 methods 数组中的索引下标 ix
获取方法的参数类型以及返回类型构建方法体 return ret= handler.invoke(this, methods[ix], args);这里的方法调用其实是委托给 InvokerInvocationHandler 实例对象的,去调用真正的实例
方法加入到 methods 数组中
4. 创建代理实例对象 ProxyInstance
类名为 pkg + “.poxy” +id = 包名 + “.poxy” +自增数值
添加静态字段 Method[] methods;
添加实例对象 InvokerInvocationHandler hanler
添加构造器参数是 InvokerInvocationHandler
添加无参构造器
利用工具类 ClassGenerator 生成对应的字节码
5. 创建代理对象,它的 newInstance(handler)方法用来创建基于我们接口的代
理代理对象名 Proxy + id 继承于 Proxy, 所以要实现 newInstance 方法
添加默认构造器实现方法 newInstance 代码, new pcn(hadler) 这里 pcn 就是前面生成的代
理对象类名利用工具类 ClassGenerator 生成字节码并实例化对象返回
public interface DemoService {
String sayHello(String name);

String sayHelloAgain(String name);
}

三、Javassist 生成伪代码
// 生成的代理对象
public class DemoService.proxy10001 implements DemoService {
public static Method[] methods = new Metod[] { "sayHello", "sayHelloAgain" };
private InvocationHandler handler;
public void DemoService.proxy10001() {}
public void DemoService.proxy10001(InvocationHandler handler) {
this.handler = handler;
}

public String sayHello(String name){
Object ret = handler.invoke(this, methods[0], new Object[]{name})
}

public String sayHello(String name){
Object ret = handler.invoke(this, methods[1], new Object[]{name})
}
}

// 生成创建代理对象的代理
public class Proxy10001 extends Proxy {
public void Proxy10001() {
}

public Object newInstance(InvocationHandler h) {
return new DemoService.proxy10001(h);
}
}
// Proxy.getProxy(DemoService).newInstance(new
// InvokerInvocationHndler(invoker))代码最终创建了基于 DemoService 接口的代理对象

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: