spring的finishRefresh中,有個步驟是回調監聽事件。因爲實現了ApplicationListener
接口,因此回調onApplicationEvent
方法。spring
沒有暴露過且沒有取消暴露apache
public void onApplicationEvent(ContextRefreshedEvent event) { if (!isExported() && !isUnexported()) { if (logger.isInfoEnabled()) { logger.info("The service ready on spring started. service: " + getInterface()); } export(); } } public void export() { super.export(); // Publish ServiceBeanExportedEvent publishExportEvent(); } private void publishExportEvent() { ServiceBeanExportedEvent exportEvent = new ServiceBeanExportedEvent(this); applicationEventPublisher.publishEvent(exportEvent); }
服務的暴露,在ServiceConfig中segmentfault
public synchronized void export() { // 各類配置的更新 checkAndUpdateSubConfigs(); if (!shouldExport()) { return; } // 延遲暴露 if (shouldDelay()) { DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS); } else { // 服務暴露 doExport(); } }
public void checkAndUpdateSubConfigs() { // Use default configs defined explicitly on global configs // 設置registries、monitor的優先級,優先級application<module<provider // 除了上面兩個,還有的設置configCenter、protocols completeCompoundConfigs(); // Config Center should always being started first. // 設置配置中心,而且把CompositeConfiguration的配置設置到Application、Monitor、Module、Protocols、Registries、Providers、Consumers中 startConfigCenter(); // 檢查provider是否存在,若是不存在,就默認一個,並調用refresh方法 checkDefault(); // 若是沒有設置protocols,會從provider中取protocols,並設置ProtocolConfig及調用refresh方法 checkProtocol(); // 檢查provider是否存在,若是不存在,就默認一個,並調用refresh方法。再根據SHUTDOWN_WAIT_KEY和SHUTDOWN_WAIT_SECONDS_KEY用於停機 checkApplication(); // if protocol is not injvm checkRegistry // 若是沒有injvm協議,就去檢查Registry if (!isOnlyInJvm()) { // 若是registries爲空,就從dubbo.registry.address獲取地址,並設置RegistryConfig及調用refresh方法 // 這裏會把註冊中心的配置,賦值給配置中心,並調用refresh方法 // 刷新後會調用prepareEnvironment方法,這裏經過SPI的方式獲取註冊中心 checkRegistry(); } // 刷新ServiceConfig this.refresh(); // 檢查metadataReportConfig是否存在,若是不存在,就默認MetadataReportConfig,並調用refresh方法。 checkMetadataReport(); // 必須有interfaceName if (StringUtils.isEmpty(interfaceName)) { throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!"); } // 泛化 if (ref instanceof GenericService) { interfaceClass = GenericService.class; if (StringUtils.isEmpty(generic)) { generic = Boolean.TRUE.toString(); } } else { try { interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } // 檢查接口和方法 checkInterfaceAndMethods(interfaceClass, methods); // 檢查ref是否有繼承關係 checkRef(); generic = Boolean.FALSE.toString(); } if (local != null) { if (Boolean.TRUE.toString().equals(local)) { local = interfaceName + "Local"; } Class<?> localClass; try { localClass = ClassUtils.forNameWithThreadContextClassLoader(local); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if (!interfaceClass.isAssignableFrom(localClass)) { throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName); } } if (stub != null) { if (Boolean.TRUE.toString().equals(stub)) { stub = interfaceName + "Stub"; } Class<?> stubClass; try { stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } if (!interfaceClass.isAssignableFrom(stubClass)) { throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName); } } checkStubAndLocal(interfaceClass); checkMock(interfaceClass); } protected synchronized void doExport() { // 已經暴露了,就再也不暴露 if (unexported) { throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!"); } if (exported) { return; } exported = true; if (StringUtils.isEmpty(path)) { path = interfaceName; } doExportUrls(); }
設置registries、monitor的優先級,優先級application<module<providerapp
private void completeCompoundConfigs() { if (provider != null) { if (application == null) { setApplication(provider.getApplication()); } if (module == null) { setModule(provider.getModule()); } if (registries == null) { setRegistries(provider.getRegistries()); } if (monitor == null) { setMonitor(provider.getMonitor()); } if (protocols == null) { setProtocols(provider.getProtocols()); } if (configCenter == null) { setConfigCenter(provider.getConfigCenter()); } } if (module != null) { // 爲空說明上面還沒設置,這裏能夠設置。若是不爲空,說明上面設置了,就不能設置。 if (registries == null) { setRegistries(module.getRegistries()); } if (monitor == null) { setMonitor(module.getMonitor()); } } if (application != null) { if (registries == null) { setRegistries(application.getRegistries()); } if (monitor == null) { setMonitor(application.getMonitor()); } } }
void startConfigCenter() { // 爲空,從餓漢單例獲取 if (configCenter == null) { ConfigManager.getInstance().getConfigCenter().ifPresent(cc -> this.configCenter = cc); } // 不爲空,刷新並環境準備、檢查 if (this.configCenter != null) { // TODO there may have duplicate refresh this.configCenter.refresh(); prepareEnvironment(); } // 刷新ApplicationConfig、MonitorConfig、ModuleConfig、ProtocolConfig、RegistryConfig、ProviderConfig、ConsumerConfig ConfigManager.getInstance().refreshAll(); }
private void prepareEnvironment() { // 檢查address、protocol的合法性 if (configCenter.isValid()) { // 已經初始化的就再也不初始化 if (!configCenter.checkOrUpdateInited()) { return; } // 獲取配置中心(這裏就有用到SPI) DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl()); // 從配置中心獲取配置 String configContent = dynamicConfiguration.getProperties(configCenter.getConfigFile(), configCenter.getGroup()); String appGroup = application != null ? application.getName() : null; String appConfigContent = null; if (StringUtils.isNotEmpty(appGroup)) { appConfigContent = dynamicConfiguration.getProperties (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(), appGroup ); } try { // 是否最高優先級 Environment.getInstance().setConfigCenterFirst(configCenter.isHighestPriority()); // 把configContent的Properties格式轉爲map並存入externalConfigurationMap Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent)); // 把appConfigContent的Properties格式轉爲map並存入appExternalConfigurationMap Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent)); } catch (IOException e) { throw new IllegalStateException("Failed to parse configurations from Config Center.", e); } } }
刷新ApplicationConfig、MonitorConfig、ModuleConfig、ProtocolConfig、RegistryConfig、ProviderConfig、ConsumerConfigjvm
public void refreshAll() { // refresh all configs here, getApplication().ifPresent(ApplicationConfig::refresh); getMonitor().ifPresent(MonitorConfig::refresh); getModule().ifPresent(ModuleConfig::refresh); getProtocols().values().forEach(ProtocolConfig::refresh); getRegistries().values().forEach(RegistryConfig::refresh); getProviders().values().forEach(ProviderConfig::refresh); getConsumers().values().forEach(ConsumerConfig::refresh); }
若是沒有provider,則建立一個,並refreshide
private void checkDefault() { createProviderIfAbsent(); } private void createProviderIfAbsent() { if (provider != null) { return; } setProvider( ConfigManager.getInstance() .getDefaultProvider() .orElseGet(() -> { ProviderConfig providerConfig = new ProviderConfig(); providerConfig.refresh(); return providerConfig; }) ); }
設置Protocolthis
private void checkProtocol() { // 若是protocols爲空,從provider取 if (CollectionUtils.isEmpty(protocols) && provider != null) { setProtocols(provider.getProtocols()); } convertProtocolIdsToProtocols(); } private void convertProtocolIdsToProtocols() { if (StringUtils.isEmpty(protocolIds) && CollectionUtils.isEmpty(protocols)) { List<String> configedProtocols = new ArrayList<>(); configedProtocols.addAll(getSubProperties(Environment.getInstance() .getExternalConfigurationMap(), PROTOCOLS_SUFFIX)); configedProtocols.addAll(getSubProperties(Environment.getInstance() .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX)); protocolIds = String.join(",", configedProtocols); } // 若是仍是沒有ProtocolConfig,則建立一個並refresh if (StringUtils.isEmpty(protocolIds)) { if (CollectionUtils.isEmpty(protocols)) { setProtocols( ConfigManager.getInstance().getDefaultProtocols() .filter(CollectionUtils::isNotEmpty) .orElseGet(() -> { ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.refresh(); return new ArrayList<>(Arrays.asList(protocolConfig)); }) ); } } else { // id賦值後refresh String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds); List<ProtocolConfig> tmpProtocols = CollectionUtils.isNotEmpty(protocols) ? protocols : new ArrayList<>(); Arrays.stream(arr).forEach(id -> { if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) { tmpProtocols.add(ConfigManager.getInstance().getProtocol(id).orElseGet(() -> { ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setId(id); protocolConfig.refresh(); return protocolConfig; })); } }); if (tmpProtocols.size() > arr.length) { throw new IllegalStateException("Too much protocols found, the protocols comply to this service are :" + protocolIds + " but got " + protocols .size() + " registries!"); } setProtocols(tmpProtocols); } }
protected void checkApplication() { // for backward compatibility // 若是沒有Application,則建立一個並refresh createApplicationIfAbsent(); // 驗證name是否爲空 if (!application.isValid()) { throw new IllegalStateException("No application config found or it's not a valid config! " + "Please add <dubbo:application name=\"...\" /> to your spring config."); } // 把name賦值給ApplicationModel的Application ApplicationModel.setApplication(application.getName()); // backward compatibility // 用於優雅停機 String wait = ConfigUtils.getProperty(SHUTDOWN_WAIT_KEY); if (wait != null && wait.trim().length() > 0) { System.setProperty(SHUTDOWN_WAIT_KEY, wait.trim()); } else { wait = ConfigUtils.getProperty(SHUTDOWN_WAIT_SECONDS_KEY); if (wait != null && wait.trim().length() > 0) { System.setProperty(SHUTDOWN_WAIT_SECONDS_KEY, wait.trim()); } } }
protected void checkRegistry() { //加載RegistryConfig loadRegistriesFromBackwardConfig(); //加載RegistryConfig convertRegistryIdsToRegistries(); // 驗證address for (RegistryConfig registryConfig : registries) { if (!registryConfig.isValid()) { throw new IllegalStateException("No registry config found or it's not a valid config! " + "The registry config is: " + registryConfig); } } useRegistryForConfigIfNecessary(); } private void useRegistryForConfigIfNecessary() { registries.stream().filter(RegistryConfig::isZookeeperProtocol).findFirst().ifPresent(rc -> { // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated. Environment.getInstance().getDynamicConfiguration().orElseGet(() -> { ConfigManager configManager = ConfigManager.getInstance(); // 建立ConfigCenterConfig ConfigCenterConfig cc = configManager.getConfigCenter().orElse(new ConfigCenterConfig()); // 設置參數 if (cc.getParameters() == null) { cc.setParameters(new HashMap<>()); } if (rc.getParameters() != null) { cc.getParameters().putAll(rc.getParameters()); } cc.getParameters().put(org.apache.dubbo.remoting.Constants.CLIENT_KEY,rc.getClient()); cc.setProtocol(rc.getProtocol()); cc.setAddress(rc.getAddress()); cc.setUsername(rc.getUsername()); cc.setPassword(rc.getPassword()); cc.setHighestPriority(false); //設置ConfigCenterConfig setConfigCenter(cc); //刷新配置 startConfigCenter(); return null; }); }); }
配置信息都好了,後面看看怎麼暴露的code