前面分析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());