前面分析SPI機制時,提到createAdaptiveExtensionClass()自動生成和編譯一個動態的adpative類。
Compiler的類繼承關係:
在Dubbo實現中,默認使用JavassistCompiler進行動態編譯,不使用JdKComplier。這一點從Compiler接口的實現中能夠看出。java
@SPI("javassist") public interface Compiler { /** * Compile java source code. * * @param code Java source code * @param classLoader TODO * @return Compiled class */ Class<?> compile(String code, ClassLoader classLoader); }
能夠看到,這裏使用了@SPI註解,指定了使用javassist。
回顧前面的調用流程:git
-->createAdaptiveExtensionClass() -->createAdaptiveExtensionClassCode() -->com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); -->compiler.compile(code, classLoader) -->AdaptiveCompiler.compile(code, classLoader) -->AbstractCompiler.compile(code, classLoader) -->Class<?> doCompile(String name, String source) -->JavassistCompiler.doCompile(String name, String source) -->cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());//編譯成class返回
根據前面分析SPI機制時得出的結論:github
getExtensionLoader(Class<T> type) 就是爲該接口new 一個ExtensionLoader,而後緩存起來。 getAdaptiveExtension() 獲取一個擴展類,若是@Adaptive註解在類上就是一個裝飾類;若是註解在方法上就是一個動態代理類,例如Protocol$Adaptive對象。 getExtension(String name) 獲取一個指定對象。
這裏首先爲Compiler接口建立了一個ExtensionLoader。而後調用getAdaptiveExtension()獲取擴展類。那麼這個Compiler是一個裝飾類仍是一個動態代理類?從上面的Compiler接口的定義並不能看出,跟進compile()方法來看:緩存
@Adaptive public class AdaptiveCompiler implements Compiler
因此Compiler是一個裝飾類。
接着看createAdaptiveExtensionClass()具體實現:spa
private Class<?> createAdaptiveExtensionClass() { String code = createAdaptiveExtensionClassCode(); ClassLoader classLoader = findClassLoader(); com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); return compiler.compile(code, classLoader); }
這裏會執行到AdaptiveCompiler的實現:代理
@Adaptive public class AdaptiveCompiler implements Compiler { private static volatile String DEFAULT_COMPILER; public static void setDefaultCompiler(String compiler) { DEFAULT_COMPILER = compiler; } public Class<?> compile(String code, ClassLoader classLoader) { Compiler compiler; ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class); String name = DEFAULT_COMPILER; // copy reference if (name != null && name.length() > 0) { compiler = loader.getExtension(name); } else { compiler = loader.getDefaultExtension(); } return compiler.compile(code, classLoader); } }
這裏DEFAULT_COMPILER執行compile時並未賦值,因此會執行else分支,這裏最終會根據@SPI("javassist")獲取JavassistCompiler。而後使用其compile()進行編譯code,這裏會調用到抽象類AbstractCompiler的實現:code
public abstract class AbstractCompiler implements Compiler { private static final Pattern PACKAGE_PATTERN = Pattern.compile("package\\s+([$_a-zA-Z][$_a-zA-Z0-9\\.]*);"); private static final Pattern CLASS_PATTERN = Pattern.compile("class\\s+([$_a-zA-Z][$_a-zA-Z0-9]*)\\s+"); public Class<?> compile(String code, ClassLoader classLoader) { code = code.trim(); Matcher matcher = PACKAGE_PATTERN.matcher(code); String pkg; if (matcher.find()) { pkg = matcher.group(1); } else { pkg = ""; } matcher = CLASS_PATTERN.matcher(code); String cls; if (matcher.find()) { cls = matcher.group(1); } else { throw new IllegalArgumentException("No such class name in " + code); } String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; try { return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass())); } catch (ClassNotFoundException e) { if (!code.endsWith("}")) { throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n"); } try { return doCompile(className, code); } catch (RuntimeException t) { throw t; } catch (Throwable t) { throw new IllegalStateException("Failed to compile class, cause: " + t.getMessage() + ", class: " + className + ", code: \n" + code + "\n, stack: " + ClassUtils.toString(t)); } } } protected abstract Class<?> doCompile(String name, String source) throws Throwable; }
在上述代碼中首先會去使用類加載器Class.forName去加載目標類,若是類自己(如動態代理類$Adaptive)不存在則會走到異常處理代碼,doCompile()這裏會調用到JavassistCompiler的具體實現。在該類中最後會返回編譯的class:對象
cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain());