前言
之前在查看源码如何根据配置来使用相应的dispatcher的时候,debug的时候,发现有个很关键的类没有找到源码,之后,对每一步进行debug查看数据流向和数据状态,才发现dubbo内部实现中,好多类都是动态加载的。
分析
直接进入根据配置调用相关dispathcer实例的地方,在类:org.apache.dubbo.remoting.transport.dispatcher.ChannelHandlers中,源码如下:
protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) {
return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class)
.getAdaptiveExtension().dispatch(handler, url)));
}
关键代码在于:ExtensionLoader.getExtensionLoader(Dispatcher.class) .getAdaptiveExtension();
在调用getAdaptiveExtension()方法的时候,如果Dispatcher实例还未构造的话,会构造这个实例,有的话就直接返回了。所以下面就按未构造的流程分析:
最终方法会进入org.apache.dubbo.common.extension.ExtensionLoader的createAdaptiveExtensionClass()方法:
private Class<?> createAdaptiveExtensionClass() {
// type=org.apache.dubbo.remoting.Dispatcher,cachedDefaultName="all"
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
// 应用类加载器
ClassLoader classLoader = findClassLoader();
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
type和cachedDefaultName的值看注释。
在generate()方法中,会构造类信息,是个字符串:
public String generate() {
// no need to generate adaptive class since there's no adaptive method found.
if (!hasAdaptiveMethod()) {
throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
}
StringBuilder code = new StringBuilder();
code.append(generatePackageInfo());
code.append(generateImports());
code.append(generateClassDeclaration());
Method[] methods = type.getMethods();
for (Method method : methods) {
code.append(generateMethod(method));
}
code.append("}");
if (logger.isDebugEnabled()) {
logger.debug(code.toString());
}
return code.toString();
}
组装包信息,导包信息,类声明信息方法信息等,生成的类代码如下:
package org.apache.dubbo.remoting;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Dispatcher$Adaptive implements org.apache.dubbo.remoting.Dispatcher {
public org.apache.dubbo.remoting.ChannelHandler dispatch(org.apache.dubbo.remoting.ChannelHandler arg0, org.apache.dubbo.common.URL arg1) {
if (arg1 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg1;
String extName = url.getParameter("dispatcher", url.getParameter("dispather", url.getParameter("channel.handler", "all")));
if (extName == null)
throw new IllegalStateException("Failed to get extension (org.apache.dubbo.remoting.Dispatcher) name from url (" + url.toString() + ") use keys([dispatcher, dispather, channel.handler])");
org.apache.dubbo.remoting.Dispatcher extension = (org.apache.dubbo.remoting.Dispatcher) ExtensionLoader.getExtensionLoader(org.apache.dubbo.remoting.Dispatcher.class).getExtension(extName);
return extension.dispatch(arg0, arg1);
}
}
首先会通过Class.forName方法通过类名来构造这个类信息,因为找不到这个类,会失败,接下来默认会使用javaassist来将这个字符串源码转换为java.lang.Class对象,动态加载这个类。如下(在org.apache.dubbo.common.compiler.support.JavassistCompiler)中:
@Override
public Class<?> doCompile(String name, String source) throws Throwable {
CtClassBuilder builder = new CtClassBuilder();
builder.setClassName(name);
// process imported classes
Matcher matcher = IMPORT_PATTERN.matcher(source);
while (matcher.find()) {
builder.addImports(matcher.group(1).trim());
}
// process extended super class
matcher = EXTENDS_PATTERN.matcher(source);
if (matcher.find()) {
builder.setSuperClassName(matcher.group(1).trim());
}
// process implemented interfaces
matcher = IMPLEMENTS_PATTERN.matcher(source);
if (matcher.find()) {
String[] ifaces = matcher.group(1).trim().split("\\,");
Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim()));
}
// process constructors, fields, methods
String body = source.substring(source.indexOf('{') + 1, source.length() - 1);
String[] methods = METHODS_PATTERN.split(body);
String className = ClassUtils.getSimpleClassName(name);
Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method -> {
if (method.startsWith(className)) {
builder.addConstructor("public " + method);
} else if (FIELD_PATTERN.matcher(method).matches()) {
builder.addField("private " + method);
} else {
builder.addMethod("public " + method);
}
});
// compile
ClassLoader classLoader = org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass());
CtClass cls = builder.build(classLoader);
return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain());
}
根据dispatcher的值来获取相关类并构造类实例:
org.apache.dubbo.remoting.Dispatcher extension = (org.apache.dubbo.remoting.Dispatcher) ExtensionLoader.getExtensionLoader(org.apache.dubbo.remoting.Dispatcher.class).getExtension(extName)
p.s. :根据getExtension方法源码实现,可以确认,如果想自己扩展的话,可以在META-INF/services/目录下,配置相关信息,如下格式:
all=org.apache.dubbo.remoting.transport.dispatcher.all.AllDispatcher
direct=org.apache.dubbo.remoting.transport.dispatcher.direct.DirectDispatcher
message=org.apache.dubbo.remoting.transport.dispatcher.message.MessageOnlyDispatcher
execution=org.apache.dubbo.remoting.transport.dispatcher.execution.ExecutionDispatcher
connection=org.apache.dubbo.remoting.transport.dispatcher.connection.ConnectionOrderedDispatcher
接下来就可以通过dispatcher的值来获取相关的dispatcher实例并调用其dispatch方法了。