dubbo源码分析-服务导出

本文深入分析了Dubbo框架的服务导出过程,从ServiceBean的onApplicationEvent方法开始,探讨了doExport和doExportUrls等关键步骤。在服务导出中,涉及到检查并加载注册中心,构建ProtocolConfig集合,并将服务注册到对应的注册中心。通过理解这些源码,有助于开发者更好地掌握Dubbo的内部工作原理。

简介

dubbo框架spring Schema扩展机制与Spring集成,在spring初始化时候加载dubbo的配置类。 dubbo服务导出的入口类是ServiceBean的onApplicationEvent方法 ServiceBean的继承关系如下

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {
    private static final long serialVersionUID = 213195494150089726L;
    private static transient ApplicationContext SPRING_CONTEXT;
    private final transient Service service;
    private transient ApplicationContext applicationContext;
    private transient String beanName;
    private transient boolean supportedApplicationListener;

    public ServiceBean() {
        this.service = null;
    }

    public ServiceBean(Service service) {
        super(service);
        this.service = service;
    }

    public static ApplicationContext getSpringContext() {
        return SPRING_CONTEXT;
    }

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
        SpringExtensionFactory.addApplicationContext(applicationContext);
        if (applicationContext != null) {
            SPRING_CONTEXT = applicationContext;

            try {
                Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class);
                method.invoke(applicationContext, this);
                this.supportedApplicationListener = true;
            } catch (Throwable var5) {
                if (applicationContext instanceof AbstractApplicationContext) {
                    try {
                        Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class);
                        if (!method.isAccessible()) {
                            method.setAccessible(true);
                        }

                        method.invoke(applicationContext, this);
                        this.supportedApplicationListener = true;
                    } catch (Throwable var4) {
                        ;
                    }
                }
            }
        }

    }

    public void setBeanName(String name) {
        this.beanName = name;
    }

    public Service getService() {
        return this.service;
    }

    public void onApplicationEvent(ContextRefreshedEvent event) {
	//如果不延迟导出且exported和unexported都为false 执行导出
        if (this.isDelay() && !this.isExported() && !this.isUnexported()) {
            if (logger.isInfoEnabled()) {
                logger.info("The service ready on spring started. service: " + this.getInterface());
            }

            this.export();
        }

    }

    private boolean isDelay() {
   //调用父类`AbstractServiceConfig`中方法
        Integer delay = this.getDelay();
        ProviderConfig provider = this.getProvider();
        if (delay == null && provider != null) {
   //调用父类`AbstractServiceConfig`中getDelay方法
            delay = provider.getDelay();
        }
     //delay == -1表示不需要延迟导出
        return this.supportedApplicationListener && (delay == null || delay == -1);
    }
}

public ProviderConfig getProvider() {
        return this.provider;
    }

supportedApplicationListener 变量含义,该变量用于表示当前的 Spring 容器是否支持 ApplicationListener,这个值初始为 false。在 Spring 容器将自己设置到 ServiceBean 中时,ServiceBean 的 setApplicationContext 方法会检测 Spring 容器是否支持 ApplicationListener。若支持,则将 supportedApplicationListener 置为 true。

this.export()调用ServiceConfig中方法

public synchronized void export() {
//如果provider存在,从provider中取export和delay属性
        if (this.provider != null) {
            if (this.export == null) {
                this.export = this.provider.getExport();
            }

            if (this.delay == null) {
                this.delay = this.provider.getDelay();
            }
        }
		//如果未导出 判断delay决定立即导出 还是延迟导出
        if (this.export == null || this.export) {
            if (this.delay != null && this.delay > 0) {
                delayExportExecutor.schedule(new Runnable() {
                    public void run() {
                        ServiceConfig.this.doExport();
                    }
                }, (long)this.delay, TimeUnit.MILLISECONDS);
            } else {
                this.doExport();
            }

        }
    }

doExport

protected synchronized void doExport() {
        if (this.unexported) {
            throw new IllegalStateException("Already unexported!");
        } else if (!this.exported) {
            this.exported = true;
            if (this.interfaceName != null && this.interfaceName.length() != 0) {
                this.checkDefault();
                if (this.provider != null) {
                    if (this.application == null) {
                        this.application = this.provider.getApplication();
                    }

                    if (this.module == null) {
                        this.module = this.provider.getModule();
                    }

                    if (this.registries == null) {
                        this.registries = this.provider.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.provider.getMonitor();
                    }

                    if (this.protocols == null) {
                        this.protocols = this.provider.getProtocols();
                    }
                }

                if (this.module != null) {
                    if (this.registries == null) {
                        this.registries = this.module.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.module.getMonitor();
                    }
                }

                if (this.application != null) {
                    if (this.registries == null) {
                        this.registries = this.application.getRegistries();
                    }

                    if (this.monitor == null) {
                        this.monitor = this.application.getMonitor();
                    }
                }
				 // 检测 ref 是否为泛化服务类型
                if (this.ref instanceof GenericService) {
                    this.interfaceClass = GenericService.class;
                    if (StringUtils.isEmpty(this.generic)) {
					// 设置 generic = "true"
                        this.generic = Boolean.TRUE.toString();
                    }
                } else {
                    try {
                        this.interfaceClass = Class.forName(this.interfaceName, true, Thread.currentThread().getContextClassLoader());
                    } catch (ClassNotFoundException var5) {
                        throw new IllegalStateException(var5.getMessage(), var5);
                    }
					//检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
                    this.checkInterfaceAndMethods(this.interfaceClass, this.methods);
					//检查ref类型是否合法
                    this.checkRef();
					// 设置 generic = "true"
                    this.generic = Boolean.FALSE.toString();
                }
				//如果loal = true 或stub = true 加载并检查本地实现是否合法
                Class stubClass;
                if (this.local != null) {
                    if ("true".equals(this.local)) {
                        this.local = this.interfaceName + "Local";
                    }

                    try {
                        stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.local);
                    } catch (ClassNotFoundException var4) {
                        throw new IllegalStateException(var4.getMessage(), var4);
                    }

                    if (!this.interfaceClass.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The local implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
                    }
                }

                if (this.stub != null) {
                    if ("true".equals(this.stub)) {
                        this.stub = this.interfaceName + "Stub";
                    }

                    try {
                        stubClass = ClassHelper.forNameWithThreadContextClassLoader(this.stub);
                    } catch (ClassNotFoundException var3) {
                        throw new IllegalStateException(var3.getMessage(), var3);
                    }

                    if (!this.interfaceClass.isAssignableFrom(stubClass)) {
                        throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + this.interfaceName);
                    }
                }
				// 检测各种对象是否为空,为空则新建,或者抛出异常
				//检查dubbo.application.name 设置系统属性dubbo.service.shutdown.wait和dubbo.service.shutdown.wait.seconds
                this.checkApplication(); 
				//检查RegistryConfig并使用set方法反射设置属性(先从系统属性中取)
                this.checkRegistry();
				//设置ProtocalConfig并使用set方法反射设置属性(先从系统属性中取)
                this.checkProtocol();
				//设置当前ServiceConfig并使用set方法反射设置属性(先从系统属性中取)
                appendProperties(this);
                this.checkStubAndMock(this.interfaceClass);
                if (this.path == null || this.path.length() == 0) {
                    this.path = this.interfaceName;
                }

                this.doExportUrls();
				 // ProviderModel 表示服务提供者模型,此对象中存储了与服务提供者相关的信息。
    			// 比如服务的配置信息,服务实例等。每个被导出的服务对应一个 ProviderModel。
    			// ApplicationModel 持有所有的 ProviderModel。
                ProviderModel providerModel = new ProviderModel(this.getUniqueServiceName(), this, this.ref);
                ApplicationModel.initProviderModel(this.getUniqueServiceName(), providerModel);
            } else {
                throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
            }
        }
    }
	//检查接口类型是否合法
	//遍历MethodConfig中方法,检查接口中是否有MethodConfig中定义的方法名称,没有抛异常
	protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
        if (interfaceClass == null) {
            throw new IllegalStateException("interface not allow null!");
        } else if (!interfaceClass.isInterface()) {
            throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
        } else {
            if (methods != null && methods.size() > 0) {
                Iterator i$ = methods.iterator();

                while(i$.hasNext()) {
                    MethodConfig methodBean = (MethodConfig)i$.next();
                    String methodName = methodBean.getName();
                    if (methodName == null || methodName.length() == 0) {
                        throw new IllegalStateException("<dubbo:method> name attribute is required! Please check: <dubbo:service interface=\"" + interfaceClass.getName() + "\" ... ><dubbo:method name=\"\" ... /></<dubbo:reference>");
                    }

                    boolean hasMethod = false;
                    Method[] arr$ = interfaceClass.getMethods();
                    int len$ = arr$.length;

                    for(int i$ = 0; i$ < len$; ++i$) {
                        Method method = arr$[i$];
                        if (method.getName().equals(methodName)) {
                            hasMethod = true;
                            break;
                        }
                    }

                    if (!hasMethod) {
                        throw new IllegalStateException("The interface " + interfaceClass.getName() + " not found method " + methodName);
                    }
                }
            }

        }
    }
	//检查ref类型是否合法
	 private void checkRef() {
        if (this.ref == null) {
            throw new IllegalStateException("ref not allow null!");
        } else if (!this.interfaceClass.isInstance(this.ref)) {
            throw new IllegalStateException("The class " + this.ref.getClass().getName() + " unimplemented interface " + this.interfaceClass + "!");
        }
    }

doExportUrls

loadRegistries 加载注册中心链接,然后再遍历 ProtocolConfig 集合导出每个服务。并在导出服务的过程中,将服务注册到注册中心。 loadRegistries 方法主要包含如下的逻辑: 检测是否存在注册中心配置类,不存在则抛出异常 构建参数映射集合,也就是 map 构建注册中心链接列表 遍历链接列表,并根据条件决定是否将其添加到 registryList 中

private void doExportUrls() {
        List<URL> registryURLs = this.loadRegistries(true);
        Iterator i$ = this.protocols.iterator();

        while(i$.hasNext()) {
            ProtocolConfig protocolConfig = (ProtocolConfig)i$.next();
            this.doExportUrlsFor1Protocol(protocolConfig, registryURLs);
        }

    }
	
protected List<URL> loadRegistries(boolean provider) {
		//检查注册中心配置
        this.checkRegistry();
        List<URL> registryList = new ArrayList();
        if (this.registries != null && this.registries.size() > 0) {
            Iterator i$ = this.registries.iterator();

            label75:
            while(true) {
                RegistryConfig config;
                String address;
                do {
                    do {
                        do {
                            if (!i$.hasNext()) {
                                return registryList;
                            }

                            config = (RegistryConfig)i$.next();
                            address = config.getAddress();
							// 若 address 为空,则将其设为 0.0.0.0
                            if (address == null || address.length() == 0) {
                                address = "0.0.0.0";
                            }
							 // 从系统属性中加载注册中心地址
                            String sysaddress = System.getProperty("dubbo.registry.address");
                            if (sysaddress != null && sysaddress.length() > 0) {
                                address = sysaddress;
                            }
                        } while(address == null);
                    } while(address.length() <= 0);
                } while("N/A".equalsIgnoreCase(address));

                Map<String, String> map = new HashMap();
				 // 添加 ApplicationConfig 中的字段信息到 map 中
                appendParameters(map, this.application);
				 // 添加 RegistryConfig 字段信息到 map 中
                appendParameters(map, config);
				 // 添加 path、pid,protocol 等信息到 map 中
                map.put("path", RegistryService.class.getName());
                map.put("dubbo", Version.getVersion());
                map.put("timestamp", String.valueOf(System.currentTimeMillis()));
                if (ConfigUtils.getPid() > 0) {
                    map.put("pid", String.valueOf(ConfigUtils.getPid()));
                }

                if (!map.containsKey("protocol")) {
                    if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {
                        map.put("protocol", "remote");
                    } else {
                        map.put("protocol", "dubbo");
                    }
                }
				// 解析得到 URL 列表,address 可能包含多个注册中心 ip,
                // 因此解析得到的是一个 URL 列表
                List<URL> urls = UrlUtils.parseURLs(address, map);
                Iterator i$ = urls.iterator();

                while(true) {
                    URL url;
                    do {
                        if (!i$.hasNext()) {
                            continue label75;
                        }

                        url = (URL)i$.next();
                        url = url.addParameter("registry", url.getProtocol());
						 // 将 URL 协议头设置为 registry
                        url = url.setProtocol("registry");
                    } while((!provider || !url.getParameter("register", true)) && (provider || !url.getParameter("subscribe", true)));

                    registryList.add(url);
                }
            }
        } else {
            return registryList;
        }
    }
//解析address 如果address以;或|符号分隔 则拆分后解析 返回List<URL>
 public static List<URL> parseURLs(String address, Map<String, String> defaults) {
        if (address != null && address.length() != 0) {
            String[] addresses = Constants.REGISTRY_SPLIT_PATTERN.split(address);
            if (addresses != null && addresses.length != 0) {
                List<URL> registries = new ArrayList();
                String[] arr$ = addresses;
                int len$ = addresses.length;

                for(int i$ = 0; i$ < len$; ++i$) {
                    String addr = arr$[i$];
                    registries.add(parseURL(addr, defaults));
                }

                return registries;
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

	public static URL parseURL(String address, Map<String, String> defaults) {
        if (address != null && address.length() != 0) {
            String url;
			//1 如果包含:// 直接返回url
			//2 否则用,拆分成address数组 后拼接url
			// 以172.19.103.55:2181,172.19.103.57:2181,172.19.103.54:2181为例
			// 返回172.19.103.55:2181?backup=172.19.103.57:2181,172.19.103.54:2181
            if (address.indexOf("://") >= 0) {
                url = address;
            } else {
                String[] addresses = Constants.COMMA_SPLIT_PATTERN.split(address);
                url = addresses[0];
                if (addresses.length > 1) {
                    StringBuilder backup = new StringBuilder();

                    for(int i = 1; i < addresses.length; ++i) {
                        if (i > 1) {
                            backup.append(",");
                        }

                        backup.append(addresses[i]);
                    }

                    url = url + "?backup=" + backup.toString();
                }
            }

            String defaultProtocol = defaults == null ? null : (String)defaults.get("protocol");
            if (defaultProtocol == null || defaultProtocol.length() == 0) {
                defaultProtocol = "dubbo";
            }

            String defaultUsername = defaults == null ? null : (String)defaults.get("username");
            String defaultPassword = defaults == null ? null : (String)defaults.get("password");
            int defaultPort = StringUtils.parseInteger(defaults == null ? null : (String)defaults.get("port"));
            String defaultPath = defaults == null ? null : (String)defaults.get("path");
            Map<String, String> defaultParameters = defaults == null ? null : new HashMap(defaults);
            if (defaultParameters != null) {
                defaultParameters.remove("protocol");
                defaultParameters.remove("username");
                defaultParameters.remove("password");
                defaultParameters.remove("host");
                defaultParameters.remove("port");
                defaultParameters.remove("path");
            }
			//构造URL
            URL u = URL.valueOf(url);
            boolean changed = false;
            String protocol = u.getProtocol();
            String username = u.getUsername();
            String password = u.getPassword();
            String host = u.getHost();
            int port = u.getPort();
            String path = u.getPath();
            Map<String, String> parameters = new HashMap(u.getParameters());
            if ((protocol == null || protocol.length() == 0) && defaultProtocol != null && defaultProtocol.length() > 0) {
                changed = true;
                protocol = defaultProtocol;
            }

            if ((username == null || username.length() == 0) && defaultUsername != null && defaultUsername.length() > 0) {
                changed = true;
                username = defaultUsername;
            }

            if ((password == null || password.length() == 0) && defaultPassword != null && defaultPassword.length() > 0) {
                changed = true;
                password = defaultPassword;
            }

            if (port <= 0) {
                if (defaultPort > 0) {
                    changed = true;
                    port = defaultPort;
                } else {
                    changed = true;
                    port = 9090;
                }
            }

            if ((path == null || path.length() == 0) && defaultPath != null && defaultPath.length() > 0) {
                changed = true;
                path = defaultPath;
            }

            if (defaultParameters != null && defaultParameters.size() > 0) {
                Iterator i$ = defaultParameters.entrySet().iterator();

                label119:
                while(true) {
                    String key;
                    String defaultValue;
                    String value;
                    do {
                        do {
                            do {
                                if (!i$.hasNext()) {
                                    break label119;
                                }

                                Entry<String, String> entry = (Entry)i$.next();
                                key = (String)entry.getKey();
                                defaultValue = (String)entry.getValue();
                            } while(defaultValue == null);
                        } while(defaultValue.length() <= 0);

                        value = (String)parameters.get(key);
                    } while(value != null && value.length() != 0);

                    changed = true;
                    parameters.put(key, defaultValue);
                }
            }
			//如果URL中有username等有一个未指定 则从默认配置读取缺失的配置
            if (changed) {
                u = new URL(protocol, username, password, host, port, path, parameters);
            }

            return u;
        } else {
            return null;
        }
    }

doExportUrlsFor1Protocol

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
        String name = protocolConfig.getName();
		//设置dubbo为默认协议
        if (name == null || name.length() == 0) {
            name = "dubbo";
        }
		// 添加 side、版本、时间戳以及进程号等信息到 map 中
        Map<String, String> map = new HashMap();
        map.put("side", "provider");
        map.put("dubbo", Version.getVersion());
        map.put("timestamp", String.valueOf(System.currentTimeMillis()));
        if (ConfigUtils.getPid() > 0) {
            map.put("pid", String.valueOf(ConfigUtils.getPid()));
        }
		// 通过反射将对象的字段信息添加到 map 中
        appendParameters(map, this.application);
        appendParameters(map, this.module);
        appendParameters(map, this.provider, "default");
        appendParameters(map, protocolConfig);
        appendParameters(map, this);
		//这段代码用于检测 <dubbo:method> 标签中的配置信息,并将相关配置添加到 map 中。
        if (this.methods != null && this.methods.size() > 0) {
            Iterator i$ = this.methods.iterator();

            label188:
            while(true) {
                MethodConfig method;
                List arguments;
                do {
                    do {
                        if (!i$.hasNext()) {
                            break label188;
                        }

                        method = (MethodConfig)i$.next();
                        appendParameters(map, method, method.getName());
                        String retryKey = method.getName() + ".retry";
                        if (map.containsKey(retryKey)) {
                            String retryValue = (String)map.remove(retryKey);
                            if ("false".equals(retryValue)) {
                                map.put(method.getName() + ".retries", "0");
                            }
                        }

                        arguments = method.getArguments();
                    } while(arguments == null);
                } while(arguments.size() <= 0);

                Iterator i$ = arguments.iterator();

                while(true) {
                    ArgumentConfig argument;
                    Method[] methods;
                    do {
                        do {
                            while(true) {
                                if (!i$.hasNext()) {
                                    continue label188;
                                }

                                argument = (ArgumentConfig)i$.next();
                                if (argument.getType() != null && argument.getType().length() > 0) {
                                    methods = this.interfaceClass.getMethods();
                                    break;
                                }

                                if (argument.getIndex() == -1) {
                                    throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
                                }

                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                            }
                        } while(methods == null);
                    } while(methods.length <= 0);

                    for(int i = 0; i < methods.length; ++i) {
                        String methodName = methods[i].getName();
                        if (methodName.equals(method.getName())) {
                            Class<?>[] argtypes = methods[i].getParameterTypes();
                            if (argument.getIndex() != -1) {
                                if (!argtypes[argument.getIndex()].getName().equals(argument.getType())) {
                                    throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                }

                                appendParameters(map, argument, method.getName() + "." + argument.getIndex());
                            } else {
                                for(int j = 0; j < argtypes.length; ++j) {
                                    Class<?> argclazz = argtypes[j];
                                    if (argclazz.getName().equals(argument.getType())) {
                                        appendParameters(map, argument, method.getName() + "." + j);
                                        if (argument.getIndex() != -1 && argument.getIndex() != j) {
                                            throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
		
        String contextPath;
        if (ProtocolUtils.isGeneric(this.generic)) {
            map.put("generic", this.generic);
            map.put("methods", "*");
        } else {
            contextPath = Version.getVersion(this.interfaceClass, this.version);
            if (contextPath != null && contextPath.length() > 0) {
                map.put("revision", contextPath);
            }
			// 为接口生成包裹类 Wrapper,Wrapper 中包含了接口的详细信息,比如接口方法名数组,字段信息等
            String[] methods = Wrapper.getWrapper(this.interfaceClass).getMethodNames();
            if (methods.length == 0) {
                logger.warn("NO method found in service interface " + this.interfaceClass.getName());
                map.put("methods", "*");
            } else {
			// 将逗号作为分隔符连接方法名,并将连接后的字符串放入 map 中
                map.put("methods", StringUtils.join(new HashSet(Arrays.asList(methods)), ","));
            }
        }
		// 添加 token 到 map 中
        if (!ConfigUtils.isEmpty(this.token)) {
            if (ConfigUtils.isDefault(this.token)) {
                map.put("token", UUID.randomUUID().toString());
            } else {
                map.put("token", this.token);
            }
        }

        if ("injvm".equals(protocolConfig.getName())) {
            protocolConfig.setRegister(false);
            map.put("notify", "false");
        }

        contextPath = protocolConfig.getContextpath();
        if ((contextPath == null || contextPath.length() == 0) && this.provider != null) {
            contextPath = this.provider.getContextpath();
        }

        String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
        Integer port = this.findConfigedPorts(protocolConfig, name, map);
		//上面的代码首先是将一些信息,比如版本、时间戳、方法名以及各种配置对象的字段信息放入到 map 中,map 中的内容将作为 URL 的查询字符串。		构建好 map 后,紧接着是获取上下文路径、主机名以及端口号等信息。最后将 map 和主机名等数据传给 URL 构造方法创建 URL 对象。
        URL url = new URL(name, host, port, (contextPath != null && contextPath.length() != 0 ? contextPath + "/" : "") + this.path, map);
        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).hasExtension(url.getProtocol())) {
            url = ((ConfiguratorFactory)ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).getExtension(url.getProtocol())).getConfigurator(url).configure(url);
        }
		
        String scope = url.getParameter("scope");
        if (!"none".toString().equalsIgnoreCase(scope)) {
            if (!"remote".toString().equalsIgnoreCase(scope)) {
                this.exportLocal(url);
            }

            if (!"local".toString().equalsIgnoreCase(scope)) {
                if (logger.isInfoEnabled()) {
                    logger.info("Export dubbo service " + this.interfaceClass.getName() + " to url " + url);
                }

                if (registryURLs != null && registryURLs.size() > 0) {
                    Iterator i$ = registryURLs.iterator();

                    while(i$.hasNext()) {
                        URL registryURL = (URL)i$.next();
                        url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));
                        URL monitorUrl = this.loadMonitor(registryURL);
                        if (monitorUrl != null) {
                            url = url.addParameterAndEncoded("monitor", monitorUrl.toFullString());
                        }

                        if (logger.isInfoEnabled()) {
                            logger.info("Register dubbo service " + this.interfaceClass.getName() + " url " + url + " to registry " + registryURL);
                        }

                        Invoker<?> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, registryURL.addParameterAndEncoded("export", url.toFullString()));
                        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
                        Exporter<?> exporter = protocol.export(wrapperInvoker);
                        this.exporters.add(exporter);
                    }
                } else {
                    Invoker<?> invoker = proxyFactory.getInvoker(this.ref, this.interfaceClass, url);
                    DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
                    Exporter<?> exporter = protocol.export(wrapperInvoker);
                    this.exporters.add(exporter);
                }
            }
        }

        this.urls.add(url);
    }

end

顺便在此给大家推荐一个Java方面的交流学习群:957734884,里面会分享一些高级面试题,还有资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系,主要针对Java开发人员提升自己,突破瓶颈,相信你来学习,会有提升和收获。在这个群里会有你需要的内容 朋友们请抓紧时间加入进来吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值