// 导出服务@Overridepublicvoidexport(RegisterTypeEnumregisterType){if(this.exported){return;}if(getScopeModel().isLifeCycleManagedExternally()){// prepare model for referencegetScopeModel().getDeployer().prepare();}else{// ensure start module, compatible with old api usagegetScopeModel().getDeployer().start();}synchronized(this){if(this.exported){return;}// 刷新配置if(!this.isRefreshed()){this.refresh();}if(this.shouldExport()){// 初始化,这里是初始化 serviceListeners 和 serviceMetadatathis.init();if(shouldDelay()){// should register if delay export// 延迟导出doDelayExport();}elseif(Integer.valueOf(-1).equals(getDelay())&&Boolean.parseBoolean(ConfigurationUtils.getProperty(getScopeModel(),CommonConstants.DUBBO_MANUAL_REGISTER_KEY,"false"))){// should not register by defaultdoExport(RegisterTypeEnum.MANUAL_REGISTER);}else{// 导出服务doExport(registerType);}}}}
protectedsynchronizedvoiddoExport(RegisterTypeEnumregisterType){if(unexported){thrownewIllegalStateException("The service "+interfaceClass.getName()+" has already unexported!");}if(exported){return;}if(StringUtils.isEmpty(path)){path=interfaceName;}// 导出 urls,这个很重要doExportUrls(registerType);// 标记已导出,执行 serviceNameMapping.map(url),这个很重要exported();}
// 导出 urls// 因为 dubbo 支持多协议服务,所以需要对每个协议执行导出服务privatevoiddoExportUrls(RegisterTypeEnumregisterType){// 获取 ServiceRepository,调用的时候,可以通过这个来获取接口的元数据信息ModuleServiceRepositoryrepository=getScopeModel().getServiceRepository();ServiceDescriptorserviceDescriptor;finalbooleanserverService=refinstanceofServerService;if(serverService){serviceDescriptor=((ServerService)ref).getServiceDescriptor();// 注册服务元数据repository.registerService(serviceDescriptor);}else{// 注册服务元数据serviceDescriptor=repository.registerService(getInterfaceClass());}// 创建 ProviderModelproviderModel=newProviderModel(serviceMetadata.getServiceKey(),ref,serviceDescriptor,getScopeModel(),serviceMetadata,interfaceClassLoader);// Compatible with dependencies on ServiceModel#getServiceConfig(), and will be removed in a future versionproviderModel.setConfig(this);providerModel.setDestroyRunner(getDestroyRunner());// 注册 providerrepository.registerProvider(providerModel);// 加载注册中心配置, 很重要List<URL>registryURLs=ConfigValidationUtils.loadRegistries(this,true);// 遍历协议for(ProtocolConfigprotocolConfig:protocols){StringpathKey=URL.buildKey(getContextPath(protocolConfig).map(p->p+"/"+path).orElse(path),group,version);// stub service will use generated service nameif(!serverService){// In case user specified path, register service one more time to map it to path.repository.registerService(pathKey,interfaceClass);}// 对每个协议导出服务,很重要doExportUrlsFor1Protocol(protocolConfig,registryURLs,registerType);}// 设置 urlsproviderModel.setServiceUrls(urls);}
// 加载注册中心配置publicstaticList<URL>loadRegistries(AbstractInterfaceConfiginterfaceConfig,booleanprovider){// check && override if necessaryList<URL>registryList=newArrayList<>();ApplicationConfigapplication=interfaceConfig.getApplication();List<RegistryConfig>registries=interfaceConfig.getRegistries();if(CollectionUtils.isNotEmpty(registries)){// 遍历 registriesfor(RegistryConfigconfig:registries){// try to refresh registry in case it is set directly by user using config.setRegistries()// 刷新配置if(!config.isRefreshed()){config.refresh();}Stringaddress=config.getAddress();if(StringUtils.isEmpty(address)){address=ANYHOST_VALUE;}// 是可用的地址if(!RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)){// 组合参数Map<String,String>map=newHashMap<String,String>();AbstractConfig.appendParameters(map,application);AbstractConfig.appendParameters(map,config);map.put(PATH_KEY,RegistryService.class.getName());AbstractInterfaceConfig.appendRuntimeParameters(map);if(!map.containsKey(PROTOCOL_KEY)){map.put(PROTOCOL_KEY,DUBBO_PROTOCOL);}List<URL>urls=UrlUtils.parseURLs(address,map);// 组合 urlfor(URLurl:urls){url=URLBuilder.from(url)// 保留原始的协议类型,对服务级别注册有用.addParameter(REGISTRY_KEY,url.getProtocol())// 提取注册类型,设置协议,这个很重要,在 dubbo 3.0 有服务级别和接口级别两种注册方式.setProtocol(extractRegistryType(url)).setScopeModel(interfaceConfig.getScopeModel()).build();// provider delay register state will be checked in RegistryProtocol#exportif(provider||url.getParameter(SUBSCRIBE_KEY,true)){registryList.add(url);}}}}}// 兼容处理,不解析returngenCompatibleRegistries(interfaceConfig.getScopeModel(),registryList,provider);}
// 导出 urlprivatevoidexportUrl(URLurl,List<URL>registryURLs,RegisterTypeEnumregisterType){// 获取 scope, scope 分为 remote 和 local, 默认为空,表示两种都会导出Stringscope=url.getParameter(SCOPE_KEY);// don't export when none is configuredif(!SCOPE_NONE.equalsIgnoreCase(scope)){// export to local if the config is not remote (export to remote only when config is remote)if(!SCOPE_REMOTE.equalsIgnoreCase(scope)){// 导出本地服务, 不解析这个exportLocal(url);}// export to remote if the config is not local (export to local only when config is local)if(!SCOPE_LOCAL.equalsIgnoreCase(scope)){// export to extra protocol is used in remote export// extProtocol 默认为空StringextProtocol=url.getParameter("ext.protocol","");List<String>protocols=newArrayList<>();if(StringUtils.isNotBlank(extProtocol)){// export original urlurl=URLBuilder.from(url).addParameter(IS_PU_SERVER_KEY,Boolean.TRUE.toString()).removeParameter("ext.protocol").build();}// 导出远程服务, 这个很重要url=exportRemote(url,registryURLs,registerType);if(!isGeneric(generic)&&!getScopeModel().isInternal()){// 元数据中心,发布服务定义,这个很重要MetadataUtils.publishServiceDefinition(url,providerModel.getServiceModel(),getApplicationModel());}if(StringUtils.isNotBlank(extProtocol)){String[]extProtocols=extProtocol.split(",",-1);protocols.addAll(Arrays.asList(extProtocols));}// export extra protocols// 导出额外协议for(Stringprotocol:protocols){if(StringUtils.isNotBlank(protocol)){URLlocalUrl=URLBuilder.from(url).setProtocol(protocol).build();// 导出远程服务, 这个很重要localUrl=exportRemote(localUrl,registryURLs,registerType);if(!isGeneric(generic)&&!getScopeModel().isInternal()){// 元数据中心,发布服务定义,这个很重要 MetadataUtils.publishServiceDefinition(localUrl,providerModel.getServiceModel(),getApplicationModel());}this.urls.add(localUrl);}}}}this.urls.add(url);}
// 对每一个注册中心,都导出接口privateURLexportRemote(URLurl,List<URL>registryURLs,RegisterTypeEnumregisterType){if(CollectionUtils.isNotEmpty(registryURLs)&®isterType!=RegisterTypeEnum.NEVER_REGISTER){// 遍历 registryUrlfor(URLregistryURL:registryURLs){// dubbo3 中是 service-registryif(SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())){url=url.addParameterIfAbsent(SERVICE_NAME_MAPPING_KEY,"true");}//if protocol is only injvm ,not register// 如果是 injvm 协议,跳过if(LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())){continue;}// 添加 dynamic 参数,表示这个接口是临时的,当注册中心注销时,需要注销这个接口url=url.addParameterIfAbsent(DYNAMIC_KEY,registryURL.getParameter(DYNAMIC_KEY));// 添加 monitor 参数URLmonitorUrl=ConfigValidationUtils.loadMonitor(this,registryURL);if(monitorUrl!=null){url=url.putAttribute(MONITOR_KEY,monitorUrl);}// For providers, this is used to enable custom proxy to generate invoker// 添加 proxy 参数,可以自定义代理实现, 默认为 javassistStringproxy=url.getParameter(PROXY_KEY);if(StringUtils.isNotEmpty(proxy)){registryURL=registryURL.addParameter(PROXY_KEY,proxy);}if(logger.isInfoEnabled()){if(url.getParameter(REGISTER_KEY,true)){logger.info("Register dubbo service "+interfaceClass.getName()+" url "+url+" to registry "+registryURL.getAddress());}else{logger.info("Export dubbo service "+interfaceClass.getName()+" to url "+url);}}// 导出 url,这里很重要,把 url 添加到 registryUrl 的 export 参数中doExportUrl(registryURL.putAttribute(EXPORT_KEY,url),true,registerType);}}else{if(logger.isInfoEnabled()){logger.info("Export dubbo service "+interfaceClass.getName()+" to url "+url);}// 导出url,不会把接口注册到注册中心doExportUrl(url,true,registerType);}returnurl;}
// 导出接口@Overridepublic<T>Exporter<T>export(finalInvoker<T>originInvoker)throwsRpcException{// 获取 registryUrlURLregistryUrl=getRegistryUrl(originInvoker);// 获取 providerUrl, 之前这个url 放在 registryUrl 的 export 参数中URLproviderUrl=getProviderUrl(originInvoker);// Subscribe the override data// FIXME When the provider subscribes, it will affect the scene : a certain JVM exposes the service and call// the same service. Because the subscribed is cached key with the name of the service, it causes the// subscription information to cover.// 一些覆盖配置的监听器,这里包括 provider, service 两个维度的finalURLoverrideSubscribeUrl=getSubscribedOverrideUrl(providerUrl);finalOverrideListeneroverrideSubscribeListener=newOverrideListener(overrideSubscribeUrl,originInvoker);Map<URL,Set<NotifyListener>>overrideListeners=getProviderConfigurationListener(overrideSubscribeUrl).getOverrideListeners();overrideListeners.computeIfAbsent(overrideSubscribeUrl,k->newConcurrentHashSet<>()).add(overrideSubscribeListener);providerUrl=overrideUrlWithConfig(providerUrl,overrideSubscribeListener);//export invoker// 导出接口,这个最重要finalExporterChangeableWrapper<T>exporter=doLocalExport(originInvoker,providerUrl);// url to registry// 根据 SPI 机制获取对应的 registry 实现类, 比如 ServiceDiscoveryRegistryfinalRegistryregistry=getRegistry(registryUrl);// 获取注册的 urlfinalURLregisteredProviderUrl=getUrlToRegistry(providerUrl,registryUrl);// decide if we need to delay publish (provider itself and registry should both need to register)// 决定是否要注册 url,刚才是 AUTO_REGISTER_BY_DEPLOYER,所以不会注册booleanregister=providerUrl.getParameter(REGISTER_KEY,true)&®istryUrl.getParameter(REGISTER_KEY,true);if(register){register(registry,registeredProviderUrl);}// register stated url on provider modelregisterStatedUrl(registryUrl,registeredProviderUrl,register);// 设置一些参数exporter.setRegisterUrl(registeredProviderUrl);exporter.setSubscribeUrl(overrideSubscribeUrl);exporter.setNotifyListener(overrideSubscribeListener);exporter.setRegistered(register);...// 执行 RegistryProtocolListener 钩子函数notifyExport(exporter);//Ensure that a new exporter instance is returned every time exportreturnnewDestroyableExporter<>(exporter);}
@Overridepublicfinalvoidregister(URLurl){if(!shouldRegister(url)){// Should Not Registerreturn;}doRegister(url);}@OverridepublicvoiddoRegister(URLurl){// fixme, add registry-cluster is not necessary anymoreurl=addRegistryClusterKey(url);// 注册 urlserviceDiscovery.register(url);}