Dubbo源码学习--服务是如何引用的
2017-01-13 14:27
489 查看
相关文章:
Dubbo源码学习文章目录ReferenceBean
跟服务引用一样,Dubbo的reference配置会被转成ReferenceBean类,ReferenceBean实现了InitializingBean接口,直接看afterPropertiesSet()也就是spring为Bean提供的初始化方法方法调用顺序afterPropertiesSet() -> getObject() -> get() -> init() -> createProxy()
afterPropertiesSet()
afterPropertiesSet()作用为装载应用信息、注册、模块、监控等配置,然后调用getObject()public void afterPropertiesSet() throws Exception { //..... setApplication(applicationConfig); //..... setModule(moduleConfig); //..... super.setRegistries(registryConfigs); //..... Boolean b = isInit(); if (b == null && getConsumer() != null) { b = getConsumer().isInit(); } if (b != null && b.booleanValue()) { getObject(); } }
getObject()
getObject() 返回 get() 执行结果public Object getObject() throws Exception { return get(); }
get()
get() 如果接口代理类(ref) 为空则调用 init() 生成接口代理类public synchronized T get() { if (destroyed){ throw new IllegalStateException("Already destroyed!"); } if (ref == null) { init(); } return ref; }
init()
init() 根据配置生成Map 然后调用 createProxy() 生成代理类ref = createProxy(map);
createProxy()
具体作用见注释private T createProxy(Map<String, String> map) { //1. 创建临时Url URL tmpUrl = new URL("temp", "localhost", 0, map); final boolean isJvmRefer; // 省略部分代码..... //2.判断是否暴漏本地服务 if (isJvmRefer) { URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map); invoker = refprotocol.refer(interfaceClass, url); // 省略部分代码..... } else { //3.判断用户指定URL,指定的URL可能是对点对直连地址,也可能是注册中心URL if (url != null && url.length() > 0) { 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 { //4. 通过注册中心配置拼装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."); } } // 5.调用refprotocol.refer() if (urls.size() == 1) { invoker = refprotocol.refer(interfaceClass, urls.get(0)); } else { 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)); } } } // 省略..... // 6.创建服务代理 return (T) proxyFactory.getProxy(invoker); }
RegistryProtocol
refprotocol.refer()
refprotocol.refer() 先后经过修饰类 ProtocolFilterWrapper、ProtocolListenerWrapper 最后执行RegistryProtocolProtocolFilterWrapper -> ProtocolListenerWrapper
//ProtocolFilterWrapper public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { return protocol.refer(type, url); } return buildInvokerChain(protocol.refer(type, url), Constants.REFERENCE_FILTER_KEY, Constants.CONSUMER); } //ProtocolListenerWrapper public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) { return protocol.refer(type, url); } return new ListenerInvokerWrapper<T>(protocol.refer(type, url), Collections.unmodifiableList( ExtensionLoader.getExtensionLoader(InvokerListener.class) .getActivateExtension(url, Constants.INVOKER_LISTENER_KEY))); }
RegistryProtocol
@SuppressWarnings("unchecked") public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException { // Constants.REGISTRY_KEY: registry // Constants.DEFAULT_REGISTRY: dubbo url = url.setProtocol(url.getParameter(Constants.REGISTRY_KEY, Constants.DEFAULT_REGISTRY)).removeParameter(Constants.REGISTRY_KEY); Registry registry = registryFactory.getRegistry(url); if (RegistryService.class.equals(type)) { return proxyFactory.getInvoker((T) registry, type, url); } // 配置Group信息 // group="a,b" or group="*" Map<String, String> qs = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY)); // Constants.REFER_KEY:refer String group = qs.get(Constants.GROUP_KEY); if (group != null && group.length() > 0 ) { if ( ( Constants.COMMA_SPLIT_PATTERN.split( group ) ).length > 1 || "*".equals( group ) ) { return doRefer( getMergeableCluster(), registry, type, url ); } } return doRefer(cluster, registry, type, url); }
doRefer()
调用FailbackRegistry.register() 在注册中心注册消费者subscribeUrl调用FailbackRegistry.subscribe() 订阅注册中心subscribeUrl
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) { RegistryDirectory<T> directory = new RegistryDirectory<T>(type, url); directory.setRegistry(registry); directory.setProtocol(protocol); // Constants.CONSUMER_PROTOCOL: consumer URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0, type.getName(), directory.getUrl().getParameters()); //consumer://10.9.22.12/com.**.ShopService?application=test&check=false&dubbo=2.8.4 //&interface=com.**.ShopService&methods=getList&pid=6168&retries=1&revision=1.0-SNAPSHOT //&side=consumer&timeout=6000×tamp=1484275807134&version=1.0 if (! Constants.ANY_VALUE.equals(url.getServiceInterface()) && url.getParameter(Constants.REGISTER_KEY, true)) { registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY, Constants.CHECK_KEY, String.valueOf(false))); } directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY + "," + Constants.CONFIGURATORS_CATEGORY + "," + Constants.ROUTERS_CATEGORY)); return cluster.join(directory); }
引用服务时序
相关文章推荐
- dubbo 源码学习笔记 (三) —— dubbo引用服务的过程
- Dubbo源码学习--服务是如何发布的
- Dubbo源码学习--服务发布(ServiceBean、ServiceConfig)
- 学习淘淘商城第十三课(引用dubbo服务)
- 学习淘淘商城第十三课(引用dubbo服务)
- Dubbo2.7源码分析-如何发布服务
- dubbo 源码学习笔记 (二) —— dubbo发布服务的过程
- Dubbo 源码学习(四)初始化过程细节:解析服务
- Dubbo暴露服务和引用服务的实现源码分析
- dubbo源码学习(五)dubbo暴露服务的过程
- dubbo源码解析(十) dubbo服务引用原理
- ARouter 学习-源码分析如何暴露服务
- Dubbo源码学习--服务发布(ProxyFactory、Invoker)
- dubbo源码分析(一) 服务暴露--服务引用
- [置顶] Dubbo暴露服务和引用服务的实现源码分析
- dubbo源码学习(四)初始化过程细节:解析服务
- Dubbo 源码学习(五)dubbo暴露服务的过程
- 引用 如何学习c#(如何学习程序语言)
- Android源码学习之一-Activity是如何实现主题变化的
- 转:CXF学习笔记二:如何在Tomcat中创建、发布和访问基于CXF的服务