服务治理中间件 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 接口的代理对象
阅读更多
相关文章推荐
- 服务治理中间件 Dubbo 原理解析(注册中心)读书笔记
- 服务治理中间件 Dubbo 原理解析(集群容错)读书笔记
- 4. Dubbo原理解析-代理之接口定义
- 分布式服务框架dubbo原理解析
- 分布式服务框架dubbo原理解析(顶)
- 分布式服务框架dubbo原理解析(转)
- 19. Dubbo原理解析-通信层之暴露服务
- 分布式服务框架dubbo原理解析
- 6. Dubbo原理解析-代理之Javassist生成的伪代码
- 9. Dubbo原理解析-服务引用
- 20. Dubbo原理解析-通信层之引用服务
- [读书笔记]深入解析MapReduce架构设计与实现原理——CH4 Java反射机制与动态代理
- dubbo服务管理中间件底层原理
- 分布式服务框架dubbo原理解析
- 分布式服务框架dubbo原理解析 转
- dubbo源码解析(十) dubbo服务引用原理
- 分布式服务框架dubbo原理解析 转
- 15. Dubbo原理解析-集群&容错之目录服务Directory
- 4. Dubbo原理解析-代理之接口定义
- 分布式服务框架dubbo原理解析 转