Dubbo源碼閱讀筆記2
阿新 • • 發佈:2018-01-26
except temp setpath available ttr blog time param provider
### 消費方初始化
消費方初始化的入口在ReferenceConfig類的get方法
前面基本和服務方的初始化一致
public class ReferenceConfig<T> extends AbstractReferenceConfig { private static final long serialVersionUID = -5864351140409987595L; private static final Protocol refprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension(); private static final Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension(); private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); private final List<URL> urls = new ArrayList<URL>(); // 接口類型 private String interfaceName; private Class<?> interfaceClass; // 客戶端類型 private String client; // 點對點直連服務提供地址 private String url; // 方法配置 private List<MethodConfig> methods; // 缺省配置 private ConsumerConfig consumer; private String protocol; // 接口代理類引用 private transient volatile T ref; // 接口調用器 private transient volatile Invoker<?> invoker; // 是否已初始化 private transient volatile boolean initialized; // 是否已銷毀 private transient volatile boolean destroyed; // ... } public synchronized T get() { if (destroyed) { throw new IllegalStateException("Already destroyed!"); } // 實現類引用不存在時初始化 if (ref == null) { init(); } return ref; } private void init() { // ... // 處理各種配置,放進map中 //attributes通過系統context進行存儲. StaticContext.getSystemContext().putAll(attributes); // 生成代理(重點方法) ref = createProxy(map); // 將實現者和配置信息封裝成model ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), this, ref, interfaceClass.getMethods()); // 放進全局context中 ApplicationModel.initConsumerModele(getUniqueServiceName(), consumerModel); }
創建代理類,代理遠程方法實現
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) { // 跟服務端的exportLocal對應 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 // 如:registry://127.0.0.1:6379/com.alibaba.dubbo.registry.RegistryService?application=demo-consumer&dubbo=2.0.0&file=${user.home}/.dubbo/dubbo-consumer.cache&owner=denis.huang&pid=15940®istry=redis&subscribe=true×tamp=1513651178925 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) { 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)); } } } 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); }
Dubbo源碼閱讀筆記2