继上一章研究provider的加载过程以后,同理consumer的加载过程基本上和provider过程如出一辙。java
一样也是先读取consumer.xml文件spring
<?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="zookeeper_privider" /> <dubbo:consumer timeout="100000" filter="DataSourceKeyFilter"/> <dubbo:registry protocol="zookeeper" address="127.0.0.1:2181" /> <dubbo:reference id="xxxService" interface="com.xxx.xx.service.xxxService" group="xyx"></dubbo:reference> </beans>
Dubbo首先使用com.alibaba.dubbo.config.spring.schema.NamespaceHandler注册解析器,当spring解析xml配置文件时就会调用这些解析器生成对应的BeanDefinition交给spring管理:app
/** * DubboNamespaceHandler * * @author william.liangf * @export */ 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 DubboBeanDefinitionParser(AnnotationBean.class, true)); }
Spring在初始化IOC容器时会利用这里注册的BeanDefinitionParser的parse方法获取对应的ReferenceBean的BeanDefinition实例,因为ReferenceBean实现了InitializingBean接口,在设置了bean的全部属性后会调用afterPropertiesSet方法:jvm
public void afterPropertiesSet() throws Exception { //若是Consumer还未注册 if (getConsumer() == null) { //获取applicationContext这个IOC容器实例中的全部ConsumerConfig Map<String, ConsumerConfig> consumerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ConsumerConfig.class, false, false); //若是IOC容器中存在这样的ConsumerConfig if (consumerConfigMap != null && consumerConfigMap.size() > 0) { ConsumerConfig consumerConfig = null; //遍历这些ConsumerConfig for (ConsumerConfig config : consumerConfigMap.values()) { //若是用户没配置Consumer系统会生成一个默认Consumer,且它的isDefault返回ture //这里是说要么是Consumer是默认的要么是用户配置的Consumer而且没设置isDefault属性 if (config.isDefault() == null || config.isDefault().booleanValue()) { //防止存在两个默认Consumer if (consumerConfig != null) { throw new IllegalStateException("Duplicate consumer configs: " + consumerConfig + " and " + config); } //获取默认Consumer consumerConfig = config; } } if (consumerConfig != null) { //设置默认Consumer setConsumer(consumerConfig); } } } //若是reference未绑定application且(reference未绑定consumer或referenc绑定的consumer没绑定application if (getApplication() == null && (getConsumer() == null || getConsumer().getApplication() == null)) { //获取IOC中全部application的实例 Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false); if (applicationConfigMap != null && applicationConfigMap.size() > 0) { //若是IOC中存在application ApplicationConfig applicationConfig = null; //遍历这些application for (ApplicationConfig config : applicationConfigMap.values()) { //若是application是默认建立或者被指定成默认 if (config.isDefault() == null || config.isDefault().booleanValue()) { if (applicationConfig != null) { throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config); } //获取application applicationConfig = config; } } if (applicationConfig != null) { //关联到reference setApplication(applicationConfig); } } } //若是reference未绑定module且(reference未绑定consumer或referenc绑定的consumer没绑定module if (getModule() == null && (getConsumer() == null || getConsumer().getModule() == null)) { //获取IOC中全部module的实例 Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false); if (moduleConfigMap != null && moduleConfigMap.size() > 0) { ModuleConfig moduleConfig = null; //遍历这些module for (ModuleConfig config : moduleConfigMap.values()) { //若是module是默认建立或者被指定成默认 if (config.isDefault() == null || config.isDefault().booleanValue()) { if (moduleConfig != null) { throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config); } //获取module moduleConfig = config; } } if (moduleConfig != null) { //关联到reference setModule(moduleConfig); } } } //若是reference未绑定注册中心(Register)且(reference未绑定consumer或referenc绑定的consumer没绑定注册中心(Register) if ((getRegistries() == null || getRegistries().size() == 0) && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().size() == 0) && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) { //获取IOC中全部的注册中心(Register)实例 Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false); if (registryConfigMap != null && registryConfigMap.size() > 0) { List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>(); //遍历这些registry for (RegistryConfig config : registryConfigMap.values()) { //若是registry是默认建立或者被指定成默认 if (config.isDefault() == null || config.isDefault().booleanValue()) { registryConfigs.add(config); } } if (registryConfigs != null && registryConfigs.size() > 0) { //关联到reference,此处能够看出一个consumer能够绑定多个registry(注册中心) super.setRegistries(registryConfigs); } } } //若是reference未绑定监控中心(Monitor)且(reference未绑定consumer或reference绑定的consumer没绑定监控中心(Monitor) if (getMonitor() == null && (getConsumer() == null || getConsumer().getMonitor() == null) && (getApplication() == null || getApplication().getMonitor() == null)) { //获取IOC中全部的监控中心(Monitor)实例 Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false); if (monitorConfigMap != null && monitorConfigMap.size() > 0) { MonitorConfig monitorConfig = null; //遍历这些监控中心(Monitor) for (MonitorConfig config : monitorConfigMap.values()) { //若是monitor是默认建立或者被指定成默认 if (config.isDefault() == null || config.isDefault().booleanValue()) { if (monitorConfig != null) { throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config); } monitorConfig = config; } } if (monitorConfig != null) { //关联到reference,一个consumer绑定到一个监控中心(monitor) setMonitor(monitorConfig); } } } Boolean b = isInit(); if (b == null && getConsumer() != null) { b = getConsumer().isInit(); } if (b != null && b.booleanValue()) { //若是consumer已经被关联则组装Reference getObject(); } } }
这步实际上是Reference确认生成Invoker所须要的组件是否已经准备好,都准备好后咱们进入生成Invoker的部分。这里的getObject会调用父类ReferenceConfig的init方法完成组装:ide
首先ReferenceConfig类的init方法调用Protocol的refer方法生成Invoker实例(如上图中的红色部分),这是服务消费的关键。接下来把Invoker转换为客户端须要的接口。详细代码以下:this
private void init() { //避免重复初始化 if (initialized) { return; } //置为已经初始化 initialized = true; //若是interfaceName不存在 if (interfaceName == null || interfaceName.length() == 0) { throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!"); } // 获取消费者 checkDefault(); appendProperties(this); //若是未使用泛接口而且consumer已经准备好的状况下,reference使用和consumer同样的泛接口 if (getGeneric() == null && getConsumer() != null) { setGeneric(getConsumer().getGeneric()); } //若是是泛接口那么interface的类型是GenericService if (ProtocolUtils.isGeneric(getGeneric())) { interfaceClass = GenericService.class; } else { //若是不是泛接口使用interfaceName指定的泛接口 try { interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() .getContextClassLoader()); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } //检查接口以及接口中的方法都是否配置齐全 checkInterfaceAndMethods(interfaceClass, methods); } //若是服务比较多能够指定dubbo-resolve.properties文件配置service(service集中配置文件) String resolve = System.getProperty(interfaceName); String resolveFile = null; if (resolve == null || resolve.length() == 0) { resolveFile = System.getProperty("dubbo.resolve.file"); if (resolveFile == null || resolveFile.length() == 0) { File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties"); if (userResolveFile.exists()) { resolveFile = userResolveFile.getAbsolutePath(); } } if (resolveFile != null && resolveFile.length() > 0) { Properties properties = new Properties(); FileInputStream fis = null; try { fis = new FileInputStream(new File(resolveFile)); properties.load(fis); } catch (IOException e) { throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e); } finally { try { if(null != fis) fis.close(); } catch (IOException e) { logger.warn(e.getMessage(), e); } } resolve = properties.getProperty(interfaceName); } } if (resolve != null && resolve.length() > 0) { url = resolve; if (logger.isWarnEnabled()) { if (resolveFile != null && resolveFile.length() > 0) { logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service."); } else { logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service."); } } } //若是application、module、registries、monitor未配置则使用consumer的 if (consumer != null) { if (application == null) { application = consumer.getApplication(); } if (module == null) { module = consumer.getModule(); } if (registries == null) { registries = consumer.getRegistries(); } if (monitor == null) { monitor = consumer.getMonitor(); } } //若是module已关联则关联module的registries和monitor if (module != null) { if (registries == null) { registries = module.getRegistries(); } if (monitor == null) { monitor = module.getMonitor(); } } //若是application已关联则关联application的registries和monitor if (application != null) { if (registries == null) { registries = application.getRegistries(); } if (monitor == null) { monitor = application.getMonitor(); } } //检查application checkApplication(); //检查远端和本地服务接口真实存在(是否可load) checkStubAndMock(interfaceClass); Map<String, String> map = new HashMap<String, String>(); //配置dubbo的端属性(是consumer仍是provider)、版本属性、建立时间、进程号 Map<Object, Object> attributes = new HashMap<Object, Object>(); map.put(Constants.SIDE_KEY, Constants.CONSUMER_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())); } if (! isGeneric()) { 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)), ",")); } } map.put(Constants.INTERFACE_KEY, interfaceName); //调用application、module、consumer的get方法将属性设置到map中 appendParameters(map, application); appendParameters(map, module); appendParameters(map, consumer, Constants.DEFAULT_KEY); appendParameters(map, this); String prifix = StringUtils.getServiceKey(map); if (methods != null && methods.size() > 0) { 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"); } } appendAttributes(attributes, method, prifix + "." + method.getName()); checkAndConvertImplicitConfig(method, map, attributes); } } //attributes经过系统context进行存储. StaticContext.getSystemContext().putAll(attributes); //在map装载了application、module、consumer、reference的全部属性信息后建立代理 ref = createProxy(map); }
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) { //此处举例说明若是是Dubbo协议则调用DubboProtocol的refer方法生成invoker,当用户调用service接口实际调用的是invoker的invoke方法 invoker = refprotocol.refer(interfaceClass, urls.get(0)); } else { //多个service生成多个invoker 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); }
至此Reference在关联了全部application、module、consumer、registry、monitor、service、protocol后调用对应Protocol类的refer方法生成InvokerProxy。当用户调用service时dubbo会经过InvokerProxy调用Invoker的invoke的方法向服务端发起请求。客户端就这样完成了本身的初始化。url
通观所有dubbo代码,有两个很重要的对象就是Invoker和Exporter,Dubbo会根据用户配置的协议调用不一样协议的Invoker,再经过ReferenceFonfig将Invoker的引用关联到Reference的ref属性上提供给消费端调用。当用户调用一个Service接口的一个方法后因为dubbo使用javassist动态代理,会调用Invoker的Invoke方法从而初始化一个RPC调用访问请求访问服务端的Service返回结果。spa