【知识库】--Dubbo ReferenceBean获取 -- 源码过程(254)
2017-07-09 08:01
381 查看
此段分析的由来:
<dubbo:reference/> 自定义标签被spring加载时生成ReferenceBean,而ReferenceBean类的定义
看到实现了spring的FactoryBean 他有一个接口用来获取代理对象:getObject().其实对于dubbo来说就是生成对远程服务调用的代理。
继续调用
继续调用:
跟进 -- getClusterInvoker(urls);
最后使用代理工厂创建--代理T
<dubbo:reference/> 自定义标签被spring加载时生成ReferenceBean,而ReferenceBean类的定义
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean
看到实现了spring的FactoryBean 他有一个接口用来获取代理对象:getObject().其实对于dubbo来说就是生成对远程服务调用的代理。
public Object getObject() throws Exception { return get(); }
继续调用
ReferenceConfig
public synchronized T get() { if (destroyed) { throw new IllegalStateException("Already destroyed!"); } if (ref == null) { init(); } return ref; }
继续调用:
private void init() { if (initialized) { return; } checkAndLoadConfig(); ref = createProxy(); initialized = true; }
@SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) private T createProxy() { URL tmpUrl = new URL("temp", "localhost", 0, initedParameterMap); if (isJvmRefer(tmpUrl)) { URL url = new URL(Constants.LOCAL_PROTO 4000 COL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(initedParameterMap); invoker = refprotocol.refer(interfaceClass, url); if (logger.isInfoEnabled()) { logger.info("Using injvm service " + interfaceClass.getName()); } } else { urls.addAll(getInvokerUrls());//获取registryUrls invoker = getClusterInvoker(urls);//伪装策略 } Boolean c = check; if (c == null && consumer != null) { c = consumer.isCheck(); } if (c == null) { c = true; // default true } if (c && !invoker.isAvailable()) { throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion()); } if (logger.isInfoEnabled()) { logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl()); } // 创建服务代理 return (T) proxyFactory.getProxy(invoker); }
private List<URL> getInvokerUrls() { List<URL> urlList = Lists.newArrayList(); if (url != null && url.length() > 0) { // 用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url); if (us != null && us.length > 0) { for (String u : us) { URL url = URL.valueOf(u); if (url.getPath() == null || url.getPath().length() == 0) { url = url.setPath(interfaceName); } if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { urlList.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(initedParameterMap))); } else { urlList.add(ClusterUtils.mergeUrl(url, initedParameterMap));//此处应该是不是dubbo://127.0.0.1:20880...等待debug } } } } else { // 通过注册中心配置拼装URL List<URL> us = loadRegistries(false); if (us != null && us.size() > 0) { for (URL u : us) { URL monitorUrl = loadMonitor(u); if (monitorUrl != null) { initedParameterMap.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString())); } Map<String, String> params = Maps.newHashMap(this.initedParameterMap); String quota = u.getParameter(Constants.REGISTRY_WEIGHT_KEY); if (!Strings.isNullOrEmpty(quota)) { params.put(Constants.REGISTRY_WEIGHT_KEY, quota); } String unit = u.getParameter(Constants.QDUBBO_UNIT); if (!Strings.isNullOrEmpty(unit)) { params.put(Constants.QDUBBO_UNIT, unit); } urlList.add(u.removeParameter(Constants.REGISTRY_WEIGHT_KEY).addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(params))); //增加REFER_KEY = "refer"; 结果例如registry://127.0.0.1:9098/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.0&pid=2484&refer=application%3Ddemo-consumer ... } } if (urlList.isEmpty()) { throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config."); } } return urlList; }
跟进 -- getClusterInvoker(urls);
@SuppressWarnings("unchecked") private Invoker<?> getClusterInvoker(List<URL> urls) { List<Invoker<?>> invokers = new ArrayList<Invoker<?>>(); URL registryURL = null; for (URL url : urls) { invokers.add(refprotocol.refer(interfaceClass, url)); //SPI扩展接口自适应获取invoker if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {// 注册中心协议 REGISTRY_PROTOCOL = "registry"; registryURL = url; // 用了最后一个registry url } } if (registryURL != null) { // 有 注册中心协议的URL if (useUnitCluster()) { URL u = registryURL.addParameterIfAbsent(Constants.REGISTRY_KEY + "." + Constants.CLUSTER_KEY, FailfastCluster.NAME); return registryCluster.join(new UnitDirectory(u, invokers)); } else { URL u = registryURL.addParameterIfAbsent(Constants.REGISTRY_KEY + "." + Constants.CLUSTER_KEY, AvailableCluster.NAME);//默认是用available策略 伪装成一个invoker return registryCluster.join(new StaticDirectory(u, invokers)); } } else { // 不是 注册中心的URL return cluster.join(new StaticDirectory(invokers)); } }
最后使用代理工厂创建--代理T
// 创建服务代理 return (T) proxyFactory.getProxy(invoker);
相关文章推荐
- 【知识库】--Dubbo ReferenceBean获取-- RegistryProtocol.Refer -- 源码过程(254)
- 【知识库】--Dubbo ReferenceBean获取-- 调用RegistryDirectory.notify -- 源码过程(254)
- 【知识库】--Dubbo ReferenceBean获取 -- router路由服务 源码过程(255)
- 【Spring源码分析】原型Bean实例化过程、byName与byType及FactoryBean获取Bean源码实现
- Spring源码阅读——Bean的加载和获取过程
- dubbo 3 ReferenceBean<T>消费者端初始化过程
- Spring源码阅读——Bean的加载和获取过程
- spring源码 — 二、从容器中获取Bean
- Tomcat Jdbc数据源初始化过程以及错误Cannot resolve reference to bean 'dataSource' while setting bean property 'da
- Spring 3.2 源码解析 -- XML bean 元素到 BeanDefinition 解析过程
- 看看Spring的源码——Bean加载过程
- Spring源码阅读3-bean获取-下
- spring 加载bean过程源码简易解剖(转载)
- dubbo源码学习(四)初始化过程细节:解析服务
- Dubbo源码分析(四):dubbo中bean的加载
- Spring源码之bean的加载(三)从bean中获取对象
- 【获取图像处理源码以及编译过程】在window下make。
- Spring源码之bean的加载(二)获取单例bean
- SSH 之 Spring的源码(一)——Bean加载过程