Dubbo—SPI及自适应扩展原理( 五 )

该方法很简单 , 就是从缓存中获取适配类对象 , 未获取到就调用createAdaptiveExtension方法加载适配类并通过反射创建对象:
private T createAdaptiveExtension() {try {// 这里又注入了些东西 , 先略过return injectExtension((T) getAdaptiveExtensionClass().newInstance());} catch (Exception e) {throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);}}调用getAdaptiveExtensionClass加载适配类:
private Class getAdaptiveExtensionClass() { // 这里刚刚分析过了 , 从配置文件中加载配置类getExtensionClasses();if (cachedAdaptiveClass != null) {return cachedAdaptiveClass;}return cachedAdaptiveClass = createAdaptiveExtensionClass();}cachedAdaptiveClass这个变量应该还没忘 , 在loadFile里赋值的 , 即我们自定义的适配扩展类 , 若没有则调用createAdaptiveExtensionClass动态创建:
private Class createAdaptiveExtensionClass() { // 生成适配类的Java代码 , 主要实现标注了@Adaptive的方法逻辑String code = createAdaptiveExtensionClassCode();ClassLoader classLoader = findClassLoader();// 调用compiler编译com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();return compiler.compile(code, classLoader);}该方法就是生成适配类的字节码 , 你一定好奇适配类的代码是怎样的 , 只需要打断点就可以看到了 , 这里我们以Protocol类的适配类为例:
import com.alibaba.dubbo.common.extension.ExtensionLoader;public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {public void destroy() {throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public int getDefaultPort() {throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");}public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) {if (arg1 == null) throw new IllegalArgumentException("url == null");com.alibaba.dubbo.common.URL url = arg1;String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.refer(arg0, arg1);}public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) {if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");if (arg0.getUrl() == null)throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null)throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);return extension.export(arg0);}}