说在前面
前期回顾
sharding-jdbc源码解析 更新完毕
spring源码解析 更新完毕
spring-mvc源码解析 更新完毕
spring-tx源码解析 更新完毕
spring-boot源码解析 更新完毕
rocketmq源码解析 更新完毕
dubbo源码解析 更新中
sharding-sphere源码解析 计划中
netty源码解析 计划中
spring-cloud-alibaba-dubbo源码解析 计划中
github https://github.com/tianheframe
sharding-jdbc源码解析 更新完毕
rocketmq 更新完毕
dubbo源码解析 更新中
seata源码解析 更新中
spring-cloud-tianhe 更新中
mq-tianhe 计划中
rpc-tianhe 计划中
更多源码解析请关注天河聊架构微信公众号
源码解析
https://github.com/tianheframe/dubbo.git dubbo源码解析后的源码和公号文章同步更新。
进入这个方法,com.alibaba.dubbo.config.ServiceConfig#exportLocal
private void exportLocal(URL url) {
// injvm协议
if (!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
URL local = URL.valueOf(url.toFullString())
.setProtocol(Constants.LOCAL_PROTOCOL)
// 127.0.0.1 本地host
.setHost(LOCALHOST)
.setPort(0);
ServiceClassHolder.getInstance().pushServiceClass(getServiceClass(ref));
// 服务注册=》
Exporter<?> exporter = protocol.export(
proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
exporters.add(exporter);
logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry");
}
}
如果scope属性指定了injvm会走export 服务 本地服务,调用这个方法proxyFactory.getInvoker会生成一个invoker的代理类,会进入到这个方法com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
// ProtocolListenerWrapper.export()
return protocol.export(invoker);
}
return protocol.export(buildInvokerChain(invoker, Constants.SERVICE_FILTER_KEY, Constants.PROVIDER));
}
进入到这个方法构建filter过滤器链,com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper#buildInvokerChain
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 过滤器链是list实现,用spi加载filter chain
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
// ConsumerContextFilter.invoke() com.alibaba.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke() com.alibaba.dubbo.monitor.support.MonitorFilter.invoke()
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
filter链数据结构是用list实现,用spi机制来实现filter chain的扩展性,dubbo默认实现了限流相关等很多过滤器链,自己也可以实现自己的filter chain实现进行扩展,比如在dubbo调用过程中处理自己的个性化的业务逻辑,这里是一个扩展点
private static <T> Invoker<T> buildInvokerChain(final Invoker<T> invoker, String key, String group) {
Invoker<T> last = invoker;
// 过滤器链是list实现,用spi加载filter chain
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(invoker.getUrl(), key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
final Filter filter = filters.get(i);
final Invoker<T> next = last;
last = new Invoker<T>() {
@Override
public Class<T> getInterface() {
return invoker.getInterface();
}
@Override
public URL getUrl() {
return invoker.getUrl();
}
@Override
public boolean isAvailable() {
return invoker.isAvailable();
}
@Override
public Result invoke(Invocation invocation) throws RpcException {
// ConsumerContextFilter.invoke() com.alibaba.dubbo.rpc.protocol.dubbo.filter.FutureFilter.invoke() com.alibaba.dubbo.monitor.support.MonitorFilter.invoke()
return filter.invoke(next, invocation);
}
@Override
public void destroy() {
invoker.destroy();
}
@Override
public String toString() {
return invoker.toString();
}
};
}
}
return last;
}
接下来会进入到这个方法,com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
if (Constants.REGISTRY_PROTOCOL.equals(invoker.getUrl().getProtocol())) {
// RegistryProtocol.export()
return protocol.export(invoker);
}
return new ListenerExporterWrapper<T>(protocol.export(invoker),
Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
.getActivateExtension(invoker.getUrl(), Constants.EXPORTER_LISTENER_KEY)));
}
com.alibaba.dubbo.rpc.ExporterListener 这里也可以实现这个接口在服务export、unexport的时候实现自己的监听器,有一个默认实现com.alibaba.dubbo.rpc.listener.ExporterListenerAdapter,如果自己需要扩展可以覆盖这个适配器类或者实现这个接口实现自己的业务逻辑
@SPI
public interface ExporterListener {
/**
* The exporter exported.
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Protocol#export(Invoker)
*/
void exported(Exporter<?> exporter) throws RpcException;
/**
* The exporter unexported.
*
* @param exporter
* @throws RpcException
* @see com.alibaba.dubbo.rpc.Exporter#unexport()
*/
void unexported(Exporter<?> exporter);
public abstract class ExporterListenerAdapter implements ExporterListener {
@Override
public void exported(Exporter<?> exporter) throws RpcException {
}
@Override
public void unexported(Exporter<?> exporter) throws RpcException {
}
}
接下来会进入到这个方法,com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol#export
@Override
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
// serviceKey=group+interface+version
return new InjvmExporter<T>(invoker, invoker.getUrl().getServiceKey(), exporterMap);
}
进入这个方法,com.alibaba.dubbo.common.URL#getServiceKey 服务的serviceKey是用group、服务接口名、version进行标识服务唯一的,服务export完毕会返回一个com.alibaba.dubbo.rpc.protocol.injvm.InjvmExporter对象,最后会返回一个com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper对象
如果scope的配置不是injvm会从远程进行服务export,下篇会介绍从远程export
说在最后
本次解析仅代表个人观点,仅供参考。