RPC 的整体消费原理是
dubbo:reference 被解析为FactoryBean, 所以在 spring容器刷新的最后一步
beanFactory.preInstantiateSingletons();
会通过 object = factory.getObject(); 创建实例, 从而调到 ReferenceBean#getObject方法,然后调用到createProxy 方法
在createProxy 方法中完成了转换为Invoker 和将Invoker转换为对应接口的操作
REF_PROTOCOL 是Protocol的自适应实现, 此时 registry://xxx , 所以会执行RegistryProtocol 的 refer方法
private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private T createProxy(Map<String, String> map) {
// ..... 省略了本地消费的,和属性获取等操作
if (urls.size() == 1) {
// 单注册中心时
invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
} else {
// 多注册中心
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
for (URL url : urls) {
// For multi-registry scenarios, it is not checked whether each referInvoker is available.
// Because this invoker may become available later.
invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
if (UrlUtils.isRegistry(url)) {
registryURL = url; // use last registry url
}
}
if (registryURL != null) {
// registry url is available
// for multi-subscription scenario, use 'zone-aware' policy by default
String cluster = registryURL.getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME);
// The invoker wrap sequence would be: ZoneAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, routing happens here) -> Invoker
invoker = Cluster.getCluster(cluster, false).join(new StaticDirectory(registryURL, invokers));
} else {
// not a registry url, must be direct invoke.
String cluster = CollectionUtils.isNotEmpty(invokers)
?
(invokers.get(0).getUrl() != null ? invokers.get(0).getUrl().getParameter