dubbo版本2.8

dubbo配置文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"><!-- 提供方应用信息,用于计算依赖关系 --><dubbo:application name="maxcar-kafka"  /><!-- 注册中心暴露服务地址 --><dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"/><!-- 用dubbo协议在20880端口暴露服务, 提高数据传输容量上限(默认为8M,即8388608)--><dubbo:protocol name="dubbo" port="20886" payload="83886080"/><!-- retries=0取消重试机制 --><dubbo:provider delay="-1" timeout="6000"  retries="0"/> <!-- 声明需要暴露的服务接口,  service实现bean必须指定名称和ref内容相同--><dubbo:service interface="com.maxcar.kafka.service.KafkaDownProducerService" ref="kafkaDownProducerService"  timeout="12000000"/><!-- 生成远程服务代理,可以和本地bean一样使用demoService --><dubbo:reference id="carService" interface="com.maxcar.stock.service.CarService" check="false"/></beans>

解析配置文件

主要用到了spring自定标签功能
定义了一个dubbo的命名空间,然后编写了对应的xsd文档,dubbo的xsd文档在jar包中的META-INF/dubbo.xsd,主要关注service和reference标签


对标签的处理类dubbo中的定义写在META-INF/spring.handlers

源码位置在

DubboNamespaceHandler

public class DubboNamespaceHandler extends NamespaceHandlerSupport {static {Version.checkDuplicate(DubboNamespaceHandler.class);}public void init() {registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());}}

dubbo自定义了一个DubboBeanDefinitionParser类去解析上面的标签,并且自定义了ServiceBean和ReferenceBean

NamespaceHandlerSupport

 /*** Stores the {@link BeanDefinitionParser} implementations keyed by the* local name of the {@link Element Elements} they handle.*/private final Map<String, BeanDefinitionParser> parsers =new HashMap<String, BeanDefinitionParser>();/*** Subclasses can call this to register the supplied {@link BeanDefinitionParser} to* handle the specified element. The element name is the local (non-namespace qualified)* name.*/protected final void registerBeanDefinitionParser(String elementName, BeanDefinitionParser parser) {this.parsers.put(elementName, parser);}

DubboBeanDefinitionParser

public class DubboBeanDefinitionParser implements BeanDefinitionParser {private static final Logger logger = LoggerFactory.getLogger(DubboBeanDefinitionParser.class);private static final Pattern GROUP_AND_VERION = Pattern.compile("^[\\-.0-9_a-zA-Z]+(\\:[\\-.0-9_a-zA-Z]+)?$");private final Class<?> beanClass;private final boolean required;public DubboBeanDefinitionParser(Class<?> beanClass, boolean required) {this.beanClass = beanClass;this.required = required;}
}

BeanDefinitionParser接口就是parse方法

public interface BeanDefinitionParser {/*** Parse the specified {@link Element} and register the resulting* {@link BeanDefinition BeanDefinition(s)} with the* {@link org.springframework.beans.factory.xml.ParserContext#getRegistry() BeanDefinitionRegistry}* embedded in the supplied {@link ParserContext}.* <p>Implementations must return the primary {@link BeanDefinition} that results* from the parse if they will ever be used in a nested fashion (for example as* an inner tag in a {@code <property/>} tag). Implementations may return* {@code null} if they will <strong>not</strong> be used in a nested fashion.* @param element the element that is to be parsed into one or more {@link BeanDefinition BeanDefinitions}* @param parserContext the object encapsulating the current state of the parsing process;* provides access to a {@link org.springframework.beans.factory.support.BeanDefinitionRegistry}* @return the primary {@link BeanDefinition}*/BeanDefinition parse(Element element, ParserContext parserContext);}

所以,DubboBeanDefinitionParser主要是parse方法

public BeanDefinition parse(Element element, ParserContext parserContext) {return parse(element, parserContext, beanClass, required);}private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {RootBeanDefinition beanDefinition = new RootBeanDefinition();beanDefinition.setBeanClass(beanClass);beanDefinition.setLazyInit(false);String id = element.getAttribute("id");if ((id == null || id.length() == 0) && required) {String generatedBeanName = element.getAttribute("name");if (generatedBeanName == null || generatedBeanName.length() == 0) {if (ProtocolConfig.class.equals(beanClass)) {generatedBeanName = "dubbo";} else {generatedBeanName = element.getAttribute("interface");}}if (generatedBeanName == null || generatedBeanName.length() == 0) {generatedBeanName = beanClass.getName();}id = generatedBeanName;int counter = 2;while (parserContext.getRegistry().containsBeanDefinition(id)) {id = generatedBeanName + (counter++);}}if (id != null && id.length() > 0) {if (parserContext.getRegistry().containsBeanDefinition(id)) {throw new IllegalStateException("Duplicate spring bean id " + id);}parserContext.getRegistry().registerBeanDefinition(id, beanDefinition);beanDefinition.getPropertyValues().addPropertyValue("id", id);}if (ProtocolConfig.class.equals(beanClass)) {for (String name : parserContext.getRegistry().getBeanDefinitionNames()) {BeanDefinition definition = parserContext.getRegistry().getBeanDefinition(name);PropertyValue property = definition.getPropertyValues().getPropertyValue("protocol");if (property != null) {Object value = property.getValue();if (value instanceof ProtocolConfig && id.equals(((ProtocolConfig) value).getName())) {definition.getPropertyValues().addPropertyValue("protocol", new RuntimeBeanReference(id));}}}} else if (ServiceBean.class.equals(beanClass)) {String className = element.getAttribute("class");if (className != null && className.length() > 0) {RootBeanDefinition classDefinition = new RootBeanDefinition();classDefinition.setBeanClass(ReflectUtils.forName(className));classDefinition.setLazyInit(false);parseProperties(element.getChildNodes(), classDefinition);beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));}} else if (ProviderConfig.class.equals(beanClass)) {parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);} else if (ConsumerConfig.class.equals(beanClass)) {parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);}Set<String> props = new HashSet<String>();ManagedMap parameters = null;for (Method setter : beanClass.getMethods()) {String name = setter.getName();if (name.length() > 3 && name.startsWith("set")&& Modifier.isPublic(setter.getModifiers())&& setter.getParameterTypes().length == 1) {Class<?> type = setter.getParameterTypes()[0];String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), "-");props.add(property);Method getter = null;try {getter = beanClass.getMethod("get" + name.substring(3), new Class<?>[0]);} catch (NoSuchMethodException e) {try {getter = beanClass.getMethod("is" + name.substring(3), new Class<?>[0]);} catch (NoSuchMethodException e2) {}}if (getter == null|| !Modifier.isPublic(getter.getModifiers())|| !type.equals(getter.getReturnType())) {continue;}if ("parameters".equals(property)) {parameters = parseParameters(element.getChildNodes(), beanDefinition);} else if ("methods".equals(property)) {parseMethods(id, element.getChildNodes(), beanDefinition, parserContext);} else if ("arguments".equals(property)) {parseArguments(id, element.getChildNodes(), beanDefinition, parserContext);} else {String value = element.getAttribute(property);if (value != null) {value = value.trim();if (value.length() > 0) {if ("registry".equals(property) && RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(value)) {RegistryConfig registryConfig = new RegistryConfig();registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);} else if ("registry".equals(property) && value.indexOf(',') != -1) {parseMultiRef("registries", value, beanDefinition, parserContext);} else if ("provider".equals(property) && value.indexOf(',') != -1) {parseMultiRef("providers", value, beanDefinition, parserContext);} else if ("protocol".equals(property) && value.indexOf(',') != -1) {parseMultiRef("protocols", value, beanDefinition, parserContext);} else {Object reference;if (isPrimitive(type)) {if ("async".equals(property) && "false".equals(value)|| "timeout".equals(property) && "0".equals(value)|| "delay".equals(property) && "0".equals(value)|| "version".equals(property) && "0.0.0".equals(value)|| "stat".equals(property) && "-1".equals(value)|| "reliable".equals(property) && "false".equals(value)) {// backward compatibility for the default value in old version's xsdvalue = null;}reference = value;} else if ("protocol".equals(property)&& ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)&& (!parserContext.getRegistry().containsBeanDefinition(value)|| !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {if ("dubbo:provider".equals(element.getTagName())) {logger.warn("Recommended replace <dubbo:provider protocol=\"" + value + "\" ... /> to <dubbo:protocol name=\"" + value + "\" ... />");}// backward compatibilityProtocolConfig protocol = new ProtocolConfig();protocol.setName(value);reference = protocol;} else if ("onreturn".equals(property)) {int index = value.lastIndexOf(".");String returnRef = value.substring(0, index);String returnMethod = value.substring(index + 1);reference = new RuntimeBeanReference(returnRef);beanDefinition.getPropertyValues().addPropertyValue("onreturnMethod", returnMethod);} else if ("onthrow".equals(property)) {int index = value.lastIndexOf(".");String throwRef = value.substring(0, index);String throwMethod = value.substring(index + 1);reference = new RuntimeBeanReference(throwRef);beanDefinition.getPropertyValues().addPropertyValue("onthrowMethod", throwMethod);} else if ("oninvoke".equals(property)) {int index = value.lastIndexOf(".");String invokeRef = value.substring(0, index);String invokeRefMethod = value.substring(index + 1);reference = new RuntimeBeanReference(invokeRef);beanDefinition.getPropertyValues().addPropertyValue("oninvokeMethod", invokeRefMethod);}else {if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);if (!refBean.isSingleton()) {throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value + "\" scope=\"singleton\" ...>");}}reference = new RuntimeBeanReference(value);}beanDefinition.getPropertyValues().addPropertyValue(property, reference);}}}}}}NamedNodeMap attributes = element.getAttributes();int len = attributes.getLength();for (int i = 0; i < len; i++) {Node node = attributes.item(i);String name = node.getLocalName();if (!props.contains(name)) {if (parameters == null) {parameters = new ManagedMap();}String value = node.getNodeValue();parameters.put(name, new TypedStringValue(value, String.class));}}if (parameters != null) {beanDefinition.getPropertyValues().addPropertyValue("parameters", parameters);}return beanDefinition;}

大体意思就是拿到xml中所有配置的基本信息,然后定义成spring中的BeanDefinition

service里面的ref参数:

    <!-- 声明需要暴露的服务接口,  service实现bean必须指定名称和ref内容相同--><dubbo:service interface="com.maxcar.kafka.service.KafkaDownProducerService" ref="kafkaDownProducerService"  timeout="12000000"/>
@Service("kafkaDownProducerService")
public class KafkaDownProducerServiceImpl implements KafkaDownProducerService

因为这里把一个interface映射到了一个可实例化的class,而且还是运行时bean的名字,所以我看了这个ref的解析实现,这个解析主要有两个:

(1).写class属性,不写ref:

        } else if (ServiceBean.class.equals(beanClass)) {String className = element.getAttribute("class");if (className != null && className.length() > 0) {RootBeanDefinition classDefinition = new RootBeanDefinition();classDefinition.setBeanClass(ReflectUtils.forName(className));classDefinition.setLazyInit(false);parseProperties(element.getChildNodes(), classDefinition);beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));}

这段的意思是如果用了class标签,spring会生成相应的class的BeanDefinition,并创建了一个BeanDefinitionHolder来代表运行时的bean,并且这个bean的名字是id+Impl。

(2)写ref,不写class。

                                }else {if ("ref".equals(property) && parserContext.getRegistry().containsBeanDefinition(value)) {BeanDefinition refBean = parserContext.getRegistry().getBeanDefinition(value);if (!refBean.isSingleton()) {throw new IllegalStateException("The exported service ref " + value + " must be singleton! Please set the " + value + " bean scope to singleton, eg: <bean id=\"" + value + "\" scope=\"singleton\" ...>");}}reference = new RuntimeBeanReference(value);}

如果有ref,就用RuntimeBeanReference作为创建时的bean。

这样就可以将本来是interface,实例化的时候是另外一个bean,并且这个bean也会存在于ioc的Bean创建链条中。

如果ref和class都写了,则以ref为准,因为ref的代码在后面,哈哈_

以上就是dubbo如何从xml读取到定义成spring的BeanDefinition

serviceBean注册服务

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;

先执行ApplicationContextAware接口

public void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;SpringExtensionFactory.addApplicationContext(applicationContext);if (applicationContext != null) {SPRING_CONTEXT = applicationContext;try {Method method = applicationContext.getClass().getMethod("addApplicationListener", new Class<?>[]{ApplicationListener.class}); // backward compatibility to spring 2.0.1method.invoke(applicationContext, new Object[]{this});supportedApplicationListener = true;} catch (Throwable t) {if (applicationContext instanceof AbstractApplicationContext) {try {Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", new Class<?>[]{ApplicationListener.class}); // backward compatibility to spring 2.0.1if (!method.isAccessible()) {method.setAccessible(true);}method.invoke(applicationContext, new Object[]{this});supportedApplicationListener = true;} catch (Throwable t2) {}}}}}

后执行InitializingBean接口

    public void afterPropertiesSet() throws Exception {if (getProvider() == null) {Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);if (providerConfigMap != null && providerConfigMap.size() > 0) {Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);if ((protocolConfigMap == null || protocolConfigMap.size() == 0)&& providerConfigMap.size() > 1) { // backward compatibilityList<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();for (ProviderConfig config : providerConfigMap.values()) {if (config.isDefault() != null && config.isDefault().booleanValue()) {providerConfigs.add(config);}}if (!providerConfigs.isEmpty()) {setProviders(providerConfigs);}} else {

最后执行ApplicationListener接口

    public void onApplicationEvent(ContextRefreshedEvent event) {if (isDelay() && !isExported() && !isUnexported()) {if (logger.isInfoEnabled()) {logger.info("The service ready on spring started. service: " + getInterface());}export();}}

基本做的也是一些初始化的变量,最后执行export方法,就是将本地服务暴露给外面调用的过程,这样就保证了spring容器在初始化完成的时候,所有的serivceBean都暴露服务了

public synchronized void export() {if (provider != null) {if (export == null) {export = provider.getExport();}if (delay == null) {delay = provider.getDelay();}}if (export != null && !export) {return;}if (delay != null && delay > 0) {delayExportExecutor.schedule(new Runnable() {public void run() {doExport();}}, delay, TimeUnit.MILLISECONDS);} else {doExport();}}protected synchronized void doExport() {if (unexported) {throw new IllegalStateException("Already unexported!");}if (exported) {return;}exported = true;if (interfaceName == null || interfaceName.length() == 0) {throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");}checkDefault();if (provider != null) {if (application == null) {application = provider.getApplication();}if (module == null) {module = provider.getModule();}if (registries == null) {registries = provider.getRegistries();}if (monitor == null) {monitor = provider.getMonitor();}if (protocols == null) {protocols = provider.getProtocols();}}if (module != null) {if (registries == null) {registries = module.getRegistries();}if (monitor == null) {monitor = module.getMonitor();}}if (application != null) {if (registries == null) {registries = application.getRegistries();}if (monitor == null) {monitor = application.getMonitor();}}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);checkRef();generic = Boolean.FALSE.toString();}if (local != null) {if ("true".equals(local)) {local = interfaceName + "Local";}Class<?> localClass;try {localClass = ClassHelper.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 ("true".equals(stub)) {stub = interfaceName + "Stub";}Class<?> stubClass;try {stubClass = ClassHelper.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);}}checkApplication();checkRegistry();checkProtocol();appendProperties(this);checkStubAndMock(interfaceClass);if (path == null || path.length() == 0) {path = interfaceName;}doExportUrls();ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), this, ref);ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);}

ServiceConfig

    private void doExportUrls() {List<URL> registryURLs = loadRegistries(true);for (ProtocolConfig protocolConfig : protocols) {doExportUrlsFor1Protocol(protocolConfig, registryURLs);}}

AbstractInterfaceConfig

protected List<URL> loadRegistries(boolean provider) {checkRegistry();List<URL> registryList = new ArrayList<URL>();if (registries != null && !registries.isEmpty()) {for (RegistryConfig config : registries) {String address = config.getAddress();if (address == null || address.length() == 0) {address = Constants.ANYHOST_VALUE;}String sysaddress = System.getProperty("dubbo.registry.address");if (sysaddress != null && sysaddress.length() > 0) {address = sysaddress;}if (address != null && address.length() > 0&& !RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {Map<String, String> map = new HashMap<String, String>();appendParameters(map, application);appendParameters(map, config);map.put("path", RegistryService.class.getName());map.put("dubbo", Version.getVersion());map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));if (ConfigUtils.getPid() > 0) {map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));}if (!map.containsKey("protocol")) {if (ExtensionLoader.getExtensionLoader(RegistryFactory.class).hasExtension("remote")) {map.put("protocol", "remote");} else {map.put("protocol", "dubbo");}}List<URL> urls = UrlUtils.parseURLs(address, map);for (URL url : urls) {url = url.addParameter(Constants.REGISTRY_KEY, url.getProtocol());url = url.setProtocol(Constants.REGISTRY_PROTOCOL);if ((provider && url.getParameter(Constants.REGISTER_KEY, true))|| (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true))) {registryList.add(url);}}}}}return registryList;}

拼接注册url

一个服务生成的url例子:
registry://172.23.2.101:2181/com.alibaba.dubbo.registry.RegistryService?application=oic-dubbo-provider&dubbo=2.6.1&logger=slf4j&pid=15258&register=true&registry=zookeeper&timestamp=1528958780785

然后再遍历protocols变量,将protocols列表中的每个protocol根据url暴露出去,主要是doExportUrlsFor1Protocol方法。
ServiceConfig

private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {String name = protocolConfig.getName();if (name == null || name.length() == 0) {name = "dubbo";}Map<String, String> map = new HashMap<String, String>();map.put(Constants.SIDE_KEY, Constants.PROVIDER_SIDE);map.put(Constants.DUBBO_VERSION_KEY, Version.getVersion());map.put(Constants.TIMESTAMP_KEY, String.valueOf(System.currentTimeMillis()));if (ConfigUtils.getPid() > 0) {map.put(Constants.PID_KEY, String.valueOf(ConfigUtils.getPid()));}appendParameters(map, application);appendParameters(map, module);appendParameters(map, provider, Constants.DEFAULT_KEY);appendParameters(map, protocolConfig);appendParameters(map, this);if (methods != null && !methods.isEmpty()) {for (MethodConfig method : methods) {appendParameters(map, method, method.getName());String retryKey = method.getName() + ".retry";if (map.containsKey(retryKey)) {String retryValue = map.remove(retryKey);if ("false".equals(retryValue)) {map.put(method.getName() + ".retries", "0");}}List<ArgumentConfig> arguments = method.getArguments();if (arguments != null && !arguments.isEmpty()) {for (ArgumentConfig argument : arguments) {// convert argument typeif (argument.getType() != null && argument.getType().length() > 0) {Method[] methods = interfaceClass.getMethods();// visit all methodsif (methods != null && methods.length > 0) {for (int i = 0; i < methods.length; i++) {String methodName = methods[i].getName();// target the method, and get its signatureif (methodName.equals(method.getName())) {Class<?>[] argtypes = methods[i].getParameterTypes();// one callback in the methodif (argument.getIndex() != -1) {if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {appendParameters(map, argument, method.getName() + "." + argument.getIndex());} else {throw new IllegalArgumentException("argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());}} else {// multiple callbacks in the methodfor (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());}}}}}}}} else if (argument.getIndex() != -1) {appendParameters(map, argument, method.getName() + "." + argument.getIndex());} else {throw new IllegalArgumentException("argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");}}}} // end of methods for}if (ProtocolUtils.isGeneric(generic)) {map.put("generic", generic);map.put("methods", Constants.ANY_VALUE);} else {String revision = Version.getVersion(interfaceClass, version);if (revision != null && revision.length() > 0) {map.put("revision", revision);}String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();if (methods.length == 0) {logger.warn("NO method found in service interface " + interfaceClass.getName());map.put("methods", Constants.ANY_VALUE);} else {map.put("methods", StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));}}if (!ConfigUtils.isEmpty(token)) {if (ConfigUtils.isDefault(token)) {map.put("token", UUID.randomUUID().toString());} else {map.put("token", token);}}if ("injvm".equals(protocolConfig.getName())) {protocolConfig.setRegister(false);map.put("notify", "false");}// export serviceString contextPath = protocolConfig.getContextpath();if ((contextPath == null || contextPath.length() == 0) && provider != null) {contextPath = provider.getContextpath();}String host = this.findConfigedHosts(protocolConfig, registryURLs, map);Integer port = this.findConfigedPorts(protocolConfig, name, map);URL url = new URL(name, host, port, (contextPath == null || contextPath.length() == 0 ? "" : contextPath + "/") + path, map);if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).hasExtension(url.getProtocol())) {url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class).getExtension(url.getProtocol()).getConfigurator(url).configure(url);}String scope = url.getParameter(Constants.SCOPE_KEY);// don't export when none is configuredif (!Constants.SCOPE_NONE.toString().equalsIgnoreCase(scope)) {// export to local if the config is not remote (export to remote only when config is remote)if (!Constants.SCOPE_REMOTE.toString().equalsIgnoreCase(scope)) {exportLocal(url);}// export to remote if the config is not local (export to local only when config is local)if (!Constants.SCOPE_LOCAL.toString().equalsIgnoreCase(scope)) {if (logger.isInfoEnabled()) {logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);}if (registryURLs != null && !registryURLs.isEmpty()) {for (URL registryURL : registryURLs) {url = url.addParameterIfAbsent("dynamic", registryURL.getParameter("dynamic"));URL monitorUrl = loadMonitor(registryURL);if (monitorUrl != null) {url = url.addParameterAndEncoded(Constants.MONITOR_KEY, monitorUrl.toFullString());}if (logger.isInfoEnabled()) {logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);}Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(Constants.EXPORT_KEY, url.toFullString()));DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);Exporter<?> exporter = protocol.export(wrapperInvoker);exporters.add(exporter);}} else {Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);Exporter<?> exporter = protocol.export(wrapperInvoker);exporters.add(exporter);}}}this.urls.add(url);}

跟上面生成registryUrl差不多,只不过多加了一些module,provider和自己的一些参数,拼成一个更长的url。下面这个就是我上面那个服务生成的完整url:

dubbo://10.8.0.28:12000/com.tyyd.oic.service.PushMessageService?accepts=1000&anyhost=true&application=oic-dubbo-provider&bind.ip=10.8.0.28&bind.port=12000&buffer=8192&charset=UTF-8&default.service.filter=dubboCallDetailFilter&dubbo=2.6.1&generic=false&interface=com.tyyd.oic.service.PushMessageService&iothreads=9&logger=slf4j&methods=deletePushMessage,getPushMessage,batchPushMessage,addPushMessage,updatePushMessage,qryPushMessage&payload=8388608&pid=15374&queues=0&retries=0&revision=1.0.0&serialization=hessian2&side=provider&threadpool=fixed&threads=100&timeout=6000&timestamp=1528959454516&version=1.0.0

dubbo源码1-暴露服务相关推荐

  1. dubbo(5) Dubbo源码解析之服务调用过程

    来源:https://juejin.im/post/5ca4a1286fb9a05e731fc042 Dubbo源码解析之服务调用过程 简介 在前面的文章中,我们分析了 Dubbo SPI.服务导出与 ...

  2. dubbo(4) Dubbo源码解析之服务引入过程

    来源:https://juejin.im/post/5ca37314e51d454cb97d9c40 1. 简介 在 Dubbo 中,我们可以通过两种方式引用远程服务.第一种是使用服务直连的方式引用服 ...

  3. Dubbo源码解析之服务路由策略

    1. 简介 服务目录在刷新 Invoker 列表的过程中,会通过 Router 进行服务路由,筛选出符合路由规则的服务提供者.在详细分析服务路由的源码之前,先来介绍一下服务路由是什么.服务路由包含一条 ...

  4. dubbo源码分析7 之 服务本地暴露

    在上一篇文章我们分析了一下 dubbo 在服务暴露发生了哪些事,今天我们就来分析一下整个服务暴露中的本地暴露.(PS:其实我感觉本地暴露蛮鸡肋的).本地暴露需要服务提供方与服务消费方在同一个 JVM. ...

  5. apache dubbo 源码分析系列汇总

    Dubbo(读音[ˈdʌbəʊ])是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成.后面捐献给了知名的开源社区 ...

  6. dubbo源码解析之框架粗谈

    dubbo框架设计 一.dubbo框架整体设计 二.各层说明 三.dubbo工程模块分包 四.依赖关系 五.调用链 文章系列 [一.dubbo源码解析之框架粗谈] [二.dubbo源码解析之dubbo ...

  7. 【Dubbo源码阅读系列】服务暴露之本地暴露

    在上一篇文章中我们介绍 Dubbo 自定义标签解析相关内容,其中我们自定义的 XML 标签 <dubbo:service /> 会被解析为 ServiceBean 对象(传送门:Dubbo ...

  8. dubbo源码学习(四):暴露服务的过程

    dubbo采用的nio异步的通信,通信协议默认为 netty,当然也可以选择 mina,grizzy.在服务端(provider)在启动时主要是开启netty监听,在zookeeper上注册服务节点, ...

  9. Dubbo 源码分析 - 服务导出

    1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可 ...

最新文章

  1. feature map 意义_FeatureMap Viewer以及中心化对统计分布变化的影响讨论
  2. 精通移动端布局 - 概念篇 -
  3. docker中创建Jmeter及在外部使用JMeter-Server控制
  4. 2016年这些网络新贵或被并购
  5. 女生心中的理想男生!这些条件你符合几条?
  6. 【无码专区1】简单路径的第二大边权(启发式合并+最小生成树)
  7. 外部表在Hive中的使用
  8. c# —— 枚举和值的隐藏副作用
  9. 第一章:了解SQL_数据库基础
  10. 剑指offer——面试题3:二维数组中的查找
  11. CDN对互联网产业的价值和作用
  12. JS:如何正确绘制文字
  13. IDEA构建Spring源码
  14. 怎么把腾讯视频qlv格式转换成为mp4视频(无需软件详细操作)
  15. 小智机器人型号_小智类人型机器人
  16. Redis-keys命令
  17. Codeforces Round #467 (Div. 2) D. Sleepy Game
  18. iPad pro能运行c语言吗,办公实战 iPad Pro还是洗洗睡吧_平板电脑评测-中关村在线...
  19. android三星note20.6,三星Galaxy Note 20 Ultra依旧是“安卓机皇”,用过的都说好
  20. parsefloat_Java Float类parseFloat()方法与示例

热门文章

  1. JavaScript学习(八十)—请写一段JS程序提取URL中的各个get参数(参数名和参数个数不确定),将其按key-value形式返回到一个json结构中
  2. 老公年收入百万,却不愿拿出二十万帮我弟弟买房子,我该离婚吗?
  3. 你是农村人吗?小时候没有自来水,每天喝的是什么水?
  4. 都说开完电动汽车,就不想再开回燃油车了,是这样吗?
  5. 做互联网项目一定要做可循环,可积累的事情
  6. 记住影响客户购买的3个决策关键
  7. 微信号也有加人涨粉规则和限制?
  8. 家里的网很慢,如何用手机查看都有多少人使用?
  9. 为什么很多程序员不用switch,而是大量的if……else if?
  10. Qt——P6 QPushButton创建