轉載自 斬秋的專欄 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生成字節碼並實例化對象返回
