【知识库】--Dubbo ReferenceBean获取 -- 源码过程(254)

来源:互联网 发布:北京房价数据库 编辑:程序博客网 时间:2024/05/27 00:45

此段分析的由来:

     <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_PROTOCOL, 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);



阅读全文
0 0
原创粉丝点击