用戶端注冊并引用服務源碼分析
getObject() 獲得服務的代理對象
- 首先或得在配置檔案中的配置的參數資訊,封裝成map,進行建立代理對象
- 在createProxy() 方法中,主要執行以下兩步操作
- 進行 Protocol#refer()操作,該方法主要有以下幾步
- 進入到RegistryProtocol#refer()方法中,打開一個zookeeper的連接配接 zookeeperRegistry
- 将consumer 協定注冊到zk上,并進行訂閱 provide、configurators、routes的變化,這裡主要是将服務的清單資訊存儲到RegistryDirectory,并進行notify()進行及時的獲得服務清單的變化以及将服務清單進行持久化到本地位址中。
- 最後根據熔斷和降級的政策,一層層的将RegistryDirectory 封裝成Invoker :MockClusterInvoker(FailoverClusterInvoker(Directory)))
-
獲得代理對象,将上步獲得Invoker 進行封裝獲得代理對象
此時獲得一個代理對象,并将上步中的Invoke通過JavassistProxyFactory 再次進行包裝,最後的結果是:Proxy0(InvokerInvocationHandler(MockClusterInvoker(FailoverClusterInvoker(Directory)))))
- 進行 Protocol#refer()操作,該方法主要有以下幾步
用戶端初始化啟動過程
ReferenceBean
啟動入口
public class ReferenceBean<T> extends ReferenceConfig<T>
implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
@Override
public Object getObject() throws Exception {
return get();
}
@Override
public Class getObjectType() {return null;}
@Override
public boolean isSingleton() {return false;}
@Override
public void afterPropertiesSet() throws Exception {
//啟動入口
getObject();
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {}
}
用戶端啟動主要做了什麼?
從
com.alibaba.dubbo.config.ReferenceConfig#createProxy
建立代理對象核心入口開始說起
将
consumer://
協定注冊到zk上,并訂閱zk其他三個目錄的變化,并拿到服務方提供的服務清單,并建立
Proxy0(InvokerInvocationHandler(MockClusterInvoker))
代理對象
@SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
private T createProxy(Map<String, String> map) {
// 當隻有一個注冊中心的時候
if (urls.size() == 1) {
// refprotocol = Protocol$Adaptive ,==>
// ProtocolListenerWrapper(ProtocolFilterWrapper(RegistryProtocol()))
// invoker = MockClusterInvoker
invoker = refprotocol.refer(interfaceClass, urls.get(0));
}
// 建立服務代理
// proxyFactory = ProxyFactory$Adaptive ==>
// StubProxyFactoryWrapper(JavassistProxyFactory())
// todo 代理的是什麼?
// 由于Dubbo 支援服務降級和熔斷機制,這裡是服務的Invoker執行個體進行一層層的包裝
// 根據順序依次是Proxy0(InvokerInvocationHandler(Invoker()))
// 由于在Protocol.refer()中進行cluster.join()操作,
// cluster.join() 該方法是将服務封裝到RegistryDirectory中,并根據服務的降級和熔斷一層層的進行封裝
// 最後會封裝成 MockClusterInvoker(FailoverClusterInvoker(Directory)))
// 最終傳回的代理對象就是 Proxy0(InvokerInvocationHandler(MockClusterInvoker(FailoverClusterInvoker(Directory)))))
return (T) proxyFactory.getProxy(invoker);
}