5.Dubbo原理解析-代理之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().inde xOf( '$') < 0 ?proxy.getClass() : type);

   return new AbstractProxyInvoker<T>(proxy, type, url) {

       protected Object doInvoke(T proxy,String methodName,

               Class<?>[] parameterTypes,Object[] arguments) ** throws** Throwable {

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

代码交流 2021