zoukankan      html  css  js  c++  java
  • dubbo源码解析(二)

    1. ReferenceBean 这个bean实现了InitializingBean接口

    2. 这个类实现了接口的afterPropertiesSet()这个方法,在spring容器启动时,property设置完之后就会调用实现了InitializingBean接口的afterPropertiesSet方法

      2.1 方法里分别对consumerConfig,applicationConfig,Module,Registries,Monitor进行了设置(取默认配置)

      2.2 在对配置进行设置完成之后判断是否进行了初始化动作,如果没有,则对消费者进行初始化操作

    3. 在这个方法内调用了getObject()方法

    4. getObject()方法又调了get()

    5. get()时如果引用为空则调用init()

    6. init()方法执行了一堆初始化操作最后调用了createProxy(map)方法

    这个方法创建了接口bean对应的代理类通过createProxy方法

    代码如下:

    private T createProxy(Map<String, String> map) {
            URL tmpUrl = new URL("temp", "localhost", 0, map);
            final boolean isJvmRefer;
            if (isInjvm() == null) {
                if (url != null && url.length() > 0) { //指定URL的情况下,不做本地引用
                    isJvmRefer = false;
                } else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
                    //默认情况下如果本地有服务暴露,则引用本地服务.
                    isJvmRefer = true;
                } else {
                    isJvmRefer = false;
                }
            } else {
                isJvmRefer = isInjvm().booleanValue();
            }
            
            if (isJvmRefer) {
                URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
                invoker = refprotocol.refer(interfaceClass, url);
                if (logger.isInfoEnabled()) {
                    logger.info("Using injvm service " + interfaceClass.getName());
                }
            } else {
                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())) {
                                urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                            } else {
                                urls.add(ClusterUtils.mergeUrl(url, map));
                            }
                        }
                    }
                } else { // 通过注册中心配置拼装URL
                    List<URL> us = loadRegistries(false);
                    if (us != null && us.size() > 0) {
                        for (URL u : us) {
                            URL monitorUrl = loadMonitor(u);
                            if (monitorUrl != null) {
                                map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
                            }
                            urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
                        }
                    }
                    if (urls == null || urls.size() == 0) {
                        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.");
                    }
                }
    
                if (urls.size() == 1) {
                    invoker = refprotocol.refer(interfaceClass, urls.get(0));
                } else {
                    List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                    URL registryURL = null;
                    for (URL url : urls) {
                        invokers.add(refprotocol.refer(interfaceClass, url));
                        if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
                            registryURL = url; // 用了最后一个registry url
                        }
                    }
                    if (registryURL != null) { // 有 注册中心协议的URL
                        // 对有注册中心的Cluster 只用 AvailableCluster
                        URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME); 
                        invoker = cluster.join(new StaticDirectory(u, invokers));
                    }  else { // 不是 注册中心的URL
                        invoker = cluster.join(new StaticDirectory(invokers));
                    }
                }
            }
    
            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);
        }

    这个方法里面有两个比较重要的地方

    1)找到协议对应的Invoker,当用户调用refer()所返回的Invoker对象的invoke()方法时,会通过对应的协议将请求发送到服务端,服务端将执行该url对应的方法,并将结果返回。具体dubbo通过什么方式将客户端请求发送到服务端将在一篇做详细说明

    /**
         * 引用远程服务:<br>
         * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。<br>
         * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。<br>
         * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。<br>
         * 
         * @param <T> 服务的类型
         * @param type 服务的类型
         * @param url 远程服务的URL地址
         * @return invoker 服务的本地代理
         * @throws RpcException 当连接服务提供方失败时抛出
         */
    refprotocol.refer(interfaceClass, urls.get(0));

    2)  通过代理工厂传入invoker创建出代理Invoker来

     proxyFactory.getProxy(invoker)

    7. proxyFactory对象是通过ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension()

    生成的具体怎么生成proxyFactory就要再看了

  • 相关阅读:
    Object-c 基础总结
    OpenCV学习(一)
    写在工作与创业间的随笔
    ASP.NET MVC5学习笔记之Action参数模型绑定之模型元数据和元数据提供
    ASP.NET MVC5学习笔记之Action参数模型绑定值提供体系
    ASP.NET MVC5学习笔记之Action参数模型绑定基本过程
    ASP.NET MVC5学习笔记之Filter提供体系
    ASP.NET MVC5学习笔记之Filter基本介绍
    ASP.NET MVC5学习笔记之Controller执行ControllerDescriptor和ActionDescriptor
    ASP.NET MVC5学习笔记之Controller同步执行架构分析
  • 原文地址:https://www.cnblogs.com/liguangming/p/9854349.html
Copyright © 2011-2022 走看看