JavassistProxyFactory利用自己吗技术构建代理对象的实现如下:

public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
}

  看似和使用jdk技术生成代理对象一样,实际上这里的Proxy类不是jdk自带的,而是dubbo自己实现的com.alibaba.dubbo.common.bytecode.Proxy,利用javassist工具生成代理代码。

  JavassistProxyFactory中获取Invoker 对象对象的实现如下:

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// TODO Wrapper类不能正确处理带$的类名
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
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从cache中查找如果有,说明代理对象已创建返回

  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生成字节码并实例化对象返回。

// create Proxy class.
String fcn = Proxy.class.getName() + id;
ccm = ClassGenerator.newInstance(cl);
ccm.setClassName(fcn);
ccm.addDefaultConstructor();
ccm.setSuperClass(Proxy.class);
ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");
Class<?> pc = ccm.toClass();
proxy = (Proxy) pc.newInstance();

Dubbo原理实现之使用Javassist字节码结束构建代理对象的更多相关文章

  1. 5.Dubbo原理解析-代理之Javassist字节码技术生成代理 (转)

    转载自  斩秋的专栏  http://blog.csdn.net/quhongwei_zhanqiu/article/details/41597219 JavassistProxyFactory:利用 ...

  2. JVM 内部原理(七)— Java 字节码基础之二

    JVM 内部原理(七)- Java 字节码基础之二 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

  3. JVM 内部原理(六)— Java 字节码基础之一

    JVM 内部原理(六)- Java 字节码基础之一 介绍 版本:Java SE 7 为什么需要了解 Java 字节码? 无论你是一名 Java 开发者.架构师.CxO 还是智能手机的普通用户,Java ...

  4. Javassist 字节码 语法 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  5. Spring AOP 源码分析 - 创建代理对象

    1.简介 在上一篇文章中,我分析了 Spring 是如何为目标 bean 筛选合适的通知器的.现在通知器选好了,接下来就要通过代理的方式将通知器(Advisor)所持有的通知(Advice)织入到 b ...

  6. 字节码技术---------动态代理,lombok插件底层原理。类加载器

    字节码技术应用场景 AOP技术.Lombok去除重复代码插件.动态修改class文件等 字节技术优势  Java字节码增强指的是在Java字节码生成之后,对其进行修改,增强其功能,这种方式相当于对应用 ...

  7. Javassist 字节码操作

    1.读写字节码 Javassist是用来处理java字节码的类库.字节码保存在二进制文件中称为类文件.每个类文件夹包括一个java类或接口. Javasssist.CtClass这个类是一个类文件的抽 ...

  8. Javassist字节码增强示例

    概述 Javassist是一款字节码编辑工具,可以直接编辑和生成Java生成的字节码,以达到对.class文件进行动态修改的效果.熟练使用这套工具,可以让Java编程更接近与动态语言编程. 下面一个方 ...

  9. JAVAssist字节码操作

    Java动态性的两种常见实现方式 字节码操作 反射 运行时操作字节码可以让我们实现如下功能: 动态生成新的类 动态改变某个类的结构(添加/删除/修改  新的属性/方法) 优势: 比反射开销小,性能高 ...

随机推荐

  1. 2017多校1 hdu-Balala Power!

    其实这道题的思路挺简单的,就是找在第一位置没有出现过并且权值小的那个字母为0. 把a~z按照权值排序,其实难就难在这里,权值很大我们怎么给他排序. 其实可以开个数组来存他们每位数是多少,然后给他们比个 ...

  2. c#中的as,is和强转

    as和强转之间的区别: as转换类型失败时不会抛出异常:强转类型失败时会抛出异常 引入is先对变量进行检验: if (foo is int) { i = (int)foo; } logger log ...

  3. Java语法基础动手动脑

    仔细阅读示例:EnumTest.Java,运行它,分析运行结果? 你能得到什么结论?你掌握了枚举类型的基本用法了吗? EnumTest.java public class EnumTest { pub ...

  4. 【转】MongoDB导入导出以及数据库备份

    -------------------MongoDB数据导入与导出------------------- 1.导出工具:mongoexport     1.概念:         mongoDB中的m ...

  5. 852. Peak Index in a Mountain Array

    class Solution { public: int peakIndexInMountainArray(vector<int>& A) { return max_element ...

  6. linux 定时器 定时执行php

    输入命令:    crontab -e 添加定时命令 每隔一分钟执行一次php //复制一下命令即可.  */1 * * * * /usr/bin/curl -o /home/logs/temp.lo ...

  7. CYS-Sqlite数据导入工具

    界面: 曹永思 下载地址:asp.net 2.0版 Sqlite数据导入工具.zip 欢迎转载,转载请注明出处,希望帮到更多人.

  8. ORA-06553: PLS-553: character set name is not recognized, while starting Content Store

    Symptom CM-CFG-5029 Content Manager is unable to determine whether the content store is initialized. ...

  9. MIT Molecular Biology 笔记1 DNA的复制,染色体组装

    视频  https://www.bilibili.com/video/av7973580?from=search&seid=16993146754254492690 教材 Molecular ...

  10. 延时、输入输出接口P0~P3

    1.寄存器 为了知道延时程序是如何工作的,我们必需首先了解延时程序中出现的一些符号,就从R1开始,R1被称之为工作寄存器.什么是工作寄存器呢?让我们从现实生活中来找找答案.如果出一道数学题:123+5 ...