概述
一、服务引用
1、初始的时候,是在spring容器初始化的时候,即要生成引用的代理类。
ReferenceBean implements InitializingBean //实现了InitializingBean,在容器初始化的时候就会执行
--ReferenceBean.afterPropertiesSet()
--ReferenceBean.getObject()//获取
--ReferenceConfig.get()
--ReferenceConfig.init()//init 方法主要用于处理配置,以及调用 createProxy 生成代理类
2、生成目标类的代理类,用于远程调用
ReferenceConfig.init()
--//刚一上来和ServiceConfig中一致,需要检查对应的配置是否完善,配置是否可用
--//之后,调用createProxy(map)//生成代理类,map中有对应的配置信息
--ReferenceConfig.createProxy()
--//1.判断是不是本地引用
final boolean isJvmRefer;
if (isInjvm() == null) {
// url被指定,直连,不做本地引用
if (url != null && url.length() > 0) { // if a url is specified, don't do local reference
isJvmRefer = false;
// 根据 url 的协议、scope 以及 injvm 等参数检测是否需要本地引用
// 比如如果用户显式配置了 scope=local,此时 isInjvmRefer 返回 true
} else if (InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl)) {
// by default, reference local service if there is
isJvmRefer = true;
} else {
isJvmRefer = false;
}
} else {
isJvmRefer = isInjvm().booleanValue();
}
--//2.如果是本地引用,生成对应的injvm协议的url,并生成对应的invoker对应
// 生成本地引用 URL,协议为 injvm
URL url = new URL(Constants.LOCAL_PROTOCOL, NetUtils.LOCALHOST, 0, interfaceClass.getName()).addParameters(map);
// 调用 refer 方法构建 InjvmInvoker 实例
invoker = refprotocol.refer(interfaceClass, url);
--//3.如果设置了url,表示想要直连生产者
String[] us = Constants.SEMICOLON_SPLIT_PATTERN.split(url);//切割url,得到直连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 = url.setPath(interfaceName);
}
// 检测 url 协议是否为 registry,若是,表明用户想使用指定的注册中心
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
// 将 map 转换为查询字符串,并作为 refer 参数的值添加到 url 中
urls.add(url.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
} else {
// 合并 url,移除服务提供者的一些配置(这些配置来源于用户配置的 url 属性),
// 比如线程池相关配置。并保留服务提供者的部分配置,比如版本,group,时间戳等
// 最后将合并后的配置设置为 url 查询字符串中。
urls.add(ClusterUtils.mergeUrl(url, map));
}
}
}
--//4.需要用到注册中心,从注册中心的配置中组装URL
List<URL> us = loadRegistries(false);
if (us != null && !us.isEmpty()) {
for (URL u : us) {
URL monitorUrl = loadMonitor(u);
if (monitorUrl != null) {
map.put(Constants.MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
}
// 添加 refer 参数到 url 中,并将 url 添加到 urls 中
urls.add(u.addParameterAndEncoded(Constants.REFER_KEY, StringUtils.toQueryString(map)));
}
}
--//5.根据配置url,判断是单注册中心还是多注册中心,或者是多服务提供者,生成对应的Invoker
if (urls.size() == 1) {
//这个地方的protocol 如果是用户自己想直连的话,没有设置url的协议,默认生成的是dubboProtocol
invoker = refprotocol.refer(interfaceClass, urls.get(0));
--DubboInvoker.refer()//直接返回DubboInvoker
--DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType, url, getClients(url), invokers);
} else {
// 多个注册中心或多个服务提供者,或者两者混合
List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
URL registryURL = null;
// 获取所有的 Invoker
for (URL url : urls) {
// 通过 refprotocol 调用 refer 构建 Invoker,refprotocol 会在运行时
// 根据 url 协议头加载指定的 Protocol 实例,并调用实例的 refer 方法
invokers.add(refprotocol.refer(interfaceClass, url));
--//通过RegistryProtocol.refer获取Invoker对象
--RegistryProtocol.doRefer()
--Invoker invoker = cluster.join(directory);//加载directory,生成MockClusterInvoker这个是个包装类,会包装默认的FailoverCluster
ProviderConsumerRegTable.registerConsumer(invoker, url, subscribeUrl, directory);
return invoker; //返回 MockClusterInvoker
if (Constants.REGISTRY_PROTOCOL.equals(url.getProtocol())) {
registryURL = url; // use last registry url
}
}
if (registryURL != null) { // registry url is available
// use AvailableCluster only when register's cluster is available
//如果注册中心链接不为空,则将使用 AvailableCluster
URL u = registryURL.addParameter(Constants.CLUSTER_KEY, AvailableCluster.NAME);
// 创建 StaticDirectory 实例,并由 Cluster 对多个 Invoker 进行合并
invoker = cluster.join(new StaticDirectory(u, invokers));
} else { // not a registry url
invoker = cluster.join(new StaticDirectory(invokers));
}
}
--//6.根据返回的Invoker生成代理里Proxy0
proxyFactory.getProxy(invoker);
--StubProxyFactoryWrapper.getProxy();
--AbstractProxyFactory.getProxy();
-- interfaces[0] = invoker.getInterface();//向代理类中注入两个接口,一个时目标接口,一个是EchoServic回声测试
interfaces[1] = EchoService.class;
--JavassistProxyFactory.getProxy(invoker,interfaces);//得到代理类
3.生成的代理类
public class proxy0
implements ClassGenerator.DC,
EchoService,
DemoService {
public static Method[] methods;
private InvocationHandler handler;
@Override
public String sayHello(String string) {
// 将参数存储到 Object 数组中
Object[] arrobject = new Object[]{string};
Object object = null;
try {
// 调用 InvocationHandler 实现类的 invoke 方法进行远程调用得到调用结果
object = this.handler.invoke(this, methods[0], arrobject);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
// 返回调用结果
return (String) object;
}
/** 回声测试方法 */
@Override
public Object $echo(Object object) {
Object[] arrobject = new Object[]{object};
Object object2 = null;
try {
object2 = this.handler.invoke(this, methods[1], arrobject);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return object2;
}
public proxy0() {
}
public proxy0(InvocationHandler invocationHandler) {
this.handler = invocationHandler;
}
}
最后
以上就是顺心时光为你收集整理的Dubbo源码分析(三)|服务引用的全部内容,希望文章能够帮你解决Dubbo源码分析(三)|服务引用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复