5.Dubbo原理解析-代理之Javassist字節碼技術生成代理 (轉)


轉載自  斬秋的專欄  http://blog.csdn.net/quhongwei_zhanqiu/article/details/41597219

 


JavassistProxyFactory:利用字節碼技術來創建對象

public <T> T getProxy(Invoker<T> invoker,Class<?>[] interfaces) { return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(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生成字節碼並實例化對象返回

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM