整体流程
服务引用流程与暴露流程一样,每一个标签都对应一个解析类
例如: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>>();
......
}