功能:具体服务转换成Invoker,Invoker 转换成 Exporter
onApplicationEvent方法会等Spring发起容器刷新事件后,开始执行服务暴露。
//☆☆---ServiceBean
public void onApplicationEvent(ContextRefreshedEvent event) {
//NOTE: 服务是否 已经暴露或者已经取消暴露
if (!isExported() && !isUnexported()) {
//NOTE: 暴露服务,ServiceConfig.export()
export();
}
}
校验用户配置是否正确,或者补齐默认配置,配置检查完成后,根据这些配置组装 URL。
采用 URL 作为配置信息的统一格式,所有扩展点都通过传递 URL 携带配置信息。
入口:checkAndUpdateSubConfigs()
入口:loadRegistries()->parseURLs()
//zk为注册中心的注册地址
zookeeper://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.2&pid=16576&qos.port=22222®istry=zookeeper×tamp=1553697573153
//
registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=demo-provider&dubbo=2.0.2&pid=16576&qos.port=22222®istry=zookeeper×tamp=1553697573153
入口:doExportUrlsFor1Protocol()
调用路径:export() -> doExportUrls -> doExportUrlsFor1Protocol()
//☆☆--ServiceConfig 基于单个协议,暴露服务
private void doExportUrls() {
// NOTE: 支持多协议多注册中心
// 加载注册中心地址
List<URL> registryURLs = loadRegistries(true);
// NOTE: 遍历protocol,向逐个注册中心分组暴露服务
for (ProtocolConfig protocolConfig : protocols) {
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}
}
服务配置暴露的 Exporter关系:
Invoker> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
Exporter> exporter = protocol.export(invoker)
Invoker> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
ProxyFactory$Adaptive
,最后创建的Invoker实际类为:AbstractProxyInvoker。//☆☆--ProxyFactory
@SPI("javassist")
public interface ProxyFactory {
/**
* create invoker.
*/
@Adaptive({Constants.PROXY_KEY})
<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
}
//☆☆--ProxyFactory$Adaptive
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
// 创建Invoker
//arg0:接口实现类
//arg1:接口
//arg2:URL对象
public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {
if (arg2 == null) {
throw new IllegalArgumentException("url == null");
}
//根据URL确定调用哪一个扩展点
org.apache.dubbo.common.URL url = arg2;
String extName = url.getParameter("proxy", "javassist");
if (extName == null) {
throw new IllegalStateException( "Fail to get extension(org.apache.dubbo.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])");
}
//获得扩展实现类(此处实际为StubProxyFactoryWrapper)
org.apache.dubbo.rpc.ProxyFactory extension = (org.apache.dubbo.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.ProxyFactory.class) .getExtension(extName);
return extension.getInvoker(arg0, arg1, arg2);
}
......
}
//创建Invoker,proxyFactory为JavassistProxyFactory
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
return proxyFactory.getInvoker(proxy, type, url);
}
/**
* proxy:实现类
* type:接口
* url:配置载体
*/
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
// NOTE: 为目标类创建 Wrapper(动态创建)
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
// NOTE: 创建 Invoker 类对象,并实现 doInvoke 方法。
return new AbstractProxyInvoker<T>(proxy, type, url) {
@Override
protected Object doInvoke(T proxy, String methodName,
Class<?>[] parameterTypes,
Object[] arguments) throws Throwable {
// NOTE: Wrapper 的 invokeMethod 方法,在服务调用时会调用具体的方法
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
其中Wrapper类动态创建代理类,将目标类进行封装,后续在服务调用时,调用AbstractProxyInvoker的doInvoker方法时,会将请求转发到Wrapper创建的代理类中的invokeMethod 方法。有点复杂,后面再分析
Protocol$Adaptive
,在export()方法中调用ProtocolListenerWrapper类;exporterMap
中)//☆☆--Protocol
@SPI("dubbo")
public interface Protocol {
//没有加@Adaptive自适应注解,不会动态生成代码
int getDefaultPort();
/**
* 服务暴露主功能入口
*/
@Adaptive
<T> Exporter<T> export(Invoker<T> invoker) throws RpcException;
}
//☆☆-- Protocol$Adaptive
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException(
"method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {
throw new UnsupportedOperationException(
"method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
//服务暴露
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) {
throw new IllegalArgumentException(
"org.apache.dubbo.rpc.Invoker argument == null");
}
if (arg0.getUrl() == null) {
throw new IllegalArgumentException(
"org.apache.dubbo.rpc.Invoker argument getUrl() == null");
}
//获取protocol name(本地导出为:injvm)
org.apache.dubbo.common.URL url = arg0.getUrl();
String extName = ((url.getProtocol() == null) ? "dubbo": url.getProtocol());
if (extName == null) {
throw new IllegalStateException(
"Fail to get extension(org.apache.dubbo.rpc.Protocol) name from url(" +
url.toString() + ") use keys([protocol])");
}
//获得扩展类,实际得到wrapper类:ProtocolListenerWrapper,内部持有InJvmProtocol引用
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
//服务暴露
return extension.export(arg0);
}
......
}
自此,服务的本地暴露,已经完成。主要流程就是将服务通过代理封装为一个Invoker,然后再有Invoker转变为Exporter的一个过程。相当于Invoker是对具体服务实现类的一个代理包裹,Invoker到Expoter,在Invoker进一步封装一些功能特性,比如:Filter、Listener等,再根据URL携带的Protocol信息,构建对应的Exporter,然后缓存在本地完成本地服务的暴露。