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