前面分析SPI机制时,提到createAdaptiveExtensionClass()自动生成和编译一个动态的adpative类。
Compiler的类继承关系:
在Dubbo实现中,默认使用JavassistCompiler进行动态编译,不使用JdKComplier。这一点从Compiler接口的实现中可以看出。
1 | "javassist") ( |
可以看到,这里使用了@SPI注解,指定了使用javassist。
回顾前面的调用流程:
1 | -->createAdaptiveExtensionClass() |
根据前面分析SPI机制时得出的结论:
1 | getExtensionLoader(Class<T> type) 就是为该接口new 一个ExtensionLoader,然后缓存起来。 |
这里首先为Compiler接口创建了一个ExtensionLoader。然后调用getAdaptiveExtension()获取扩展类。那么这个Compiler是一个装饰类还是一个动态代理类?从上面的Compiler接口的定义并不能看出,跟进compile()方法来看:
1 |
|
所以Compiler是一个装饰类。
接着看createAdaptiveExtensionClass()具体实现:
1 | private Class<?> createAdaptiveExtensionClass() { |
这里会执行到AdaptiveCompiler的实现:
1 |
|
这里DEFAULT_COMPILER执行compile时并未赋值,所以会执行else分支,这里最终会根据@SPI(“javassist”)获取JavassistCompiler。然后使用其compile()进行编译code,这里会调用到抽象类AbstractCompiler的实现:
1 | public abstract class AbstractCompiler implements Compiler { |
在上述代码中首先会去使用类加载器Class.forName去加载目标类,如果类本身(如动态代理类$Adaptive)不存在则会走到异常处理代码,doCompile()这里会调用到JavassistCompiler的具体实现。
在该类中最后会返回编译的class:
1 | cls.toClass(ClassHelper.getCallerClassLoader(getClass()), JavassistCompiler.class.getProtectionDomain()); |