整體流程
服務引用流程與暴露流程一樣,每一個標籤都對應一個解析類
例如:referenceBean對應的解析類是com.alibaba.dubbo.config.spring.ReferenceBean
@Autowired註解通過調用 get方法從容器中獲取refence標籤中配置的實體類
// 繼承了RefenceConfig,實現了FactoryBean
public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {
private static final long serialVersionUID = 213195494150089726L;
private transient ApplicationContext applicationContext;
public ReferenceBean() {
super();
}
public ReferenceBean(Reference reference) {
super(reference);
}
......
// 工廠Bean
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
}
// <dubbo:reference id="queryService" interface="com.yaoyagang.api.QueryService"
//retries="0" timeout="3000" check="false"/>
@Override
public Object getObject() throws Exception {
// 調用get方法從容器中獲取refence標籤中配置的實體類
return get();
}
@Override
public Class<?> getObjectType() {
// 獲取com.alibaba.dubbo.config.ReferenceConfig
return getInterfaceClass();
}
@Override
@Parameter(excluded = true)
public boolean isSingleton() {
return true;
}
@Override
@SuppressWarnings({"unchecked"})
public void afterPropertiesSet() throws Exception {
......
}
@Override
public void destroy() {
// do nothing
}
從註冊中心遠程獲取privode的接口
referenceConfig中的init方法中:
// 消費者需要引用的接口類名,urls配置中心的url
invoker = refprotocol.refer(interfaceClass, urls.get(0));
調用RegistryProtocol的refer方法
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
......
// 獲取註冊中心的信息
Registry registry = this.registryFactory.getRegistry(url);
......
// 調用doRefer方法
// registry:註冊中心的地址,type:需要引用的service類,url:註冊中心的地址
this.doRefer(this.cluster, registry, type, url)
}
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
RegistryDirectory<T> directory = new RegistryDirectory(type, url);
directory.setRegistry(registry);
directory.setProtocol(this.protocol);
// 訂閱註冊中心的服務者提供的服務
directory.subscribe(subscribeUrl.addParameter("category","providers,configurators,routers"));
}
訂閱服務會進去到DubboProtocol,調用refer方法
@Override
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// serviceType:服務提供者service類,url:註冊中心地址,getClients獲取客戶端
// 獲取執行者
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
private ExchangeClient[] getClients(URL url) {
// 根據連接數獲取客戶端,底層是通過netty實現的
ExchangeClient[] clients = new ExchangeClient[connections];
}
獲取到執行者之後,返回到RegistryProtocol中的doRefer方法
private <T> Invoker<T> doRefer(Cluster cluster, Registry registry, Class<T> type, URL url) {
RegistryDirectory<T> directory = new RegistryDirectory(type, url);
directory.setRegistry(registry);
directory.setProtocol(this.protocol);
......
// 訂閱
directory.subscribe(subscribeUrl.addParameter("category", "providers,configurators,routers"));
// 獲取執行者:invoker中有服務提供者的相關信息
Invoker invoker = cluster.join(directory);
// 把invoker放入註冊表中
// subscribeUrl爲消費者的相關信息
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker;
}
.....
}
註冊表ProviderConsumerRegTable
public class ProviderConsumerRegTable {
// 提供者Url以及其他信息
public static ConcurrentHashMap<String, Set<ProviderInvokerWrapper>> providerInvokers = new ConcurrentHashMap<String, Set<ProviderInvokerWrapper>>();
// 消費者Url以及消費者的代理對象Invoke
public static ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>> consumerInvokers = new ConcurrentHashMap<String, Set<ConsumerInvokerWrapper>>();
......
}