1. dubbo为什么需要SPI
dubbo的SPI作用主要是扩展性,当一个接口存在多种实现,如何在代码运行过程中,根据不同的参数选择不同的实现;
java中也提供了SPI,只是它的SPI过于简单:
- 一次性全部加载所有实现,无法做到懒加载;
- java的SPI无法实现控制反转,对于实现如果有依赖其他类,无法自动注入;
所以在dubbo中引入了自定义的SPI组件;
2. dubbo的SPI源码分析
dubbo的SPI主要包括四个方法:
- ExtensionLoader.getExtensionLoader(Class);
- ExtensionLoader.getExtensionLoader(SimpleExt.class).getAdaptiveExtension();
- ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension(String);
- ExtensionLoader.getExtensionLoader(SimpleExt.class).getDefaultExtension();
后面三个方法是获取具体的实现,第一个是获取一个加载器,我们先从第一个看起:
2.1 getExtensionLoader
2.1. 源码分析
源码分析,我们先从这里开始吧:
@Test
public void test_Debug_GetExtension_Process() throws Exception {
final ExtensionLoader<SimpleExt> extensionLoader = ExtensionLoader.getExtensionLoader(SimpleExt.class);
System.out.println(extensionLoader);
}
1. ExtensionLoader#getExtensionLoader(Class type)
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
// 如果为空,报错
if (type == null)
throw new IllegalArgumentException("Extension type == null");
// 如果不是接口,报错,因为SPI是针对接口的扩展
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
}
// 接口上是否有SPI注解
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type(" + type +
") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
}
// 从缓存中获取
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
// 如果缓存中没有获取到
if (loader == null) {
// 创建一个ExtensionLoader,并添加到缓存中;
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
2.ExtensionLoader#ExtensionLoader构造器
private ExtensionLoader(Class<?> type) {
this.type = type;
// 我们传入的是SimpleExt.class,所以会执行else;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()这段代码,getAdaptiveExtension()
之前跟我们前面分析的是一样的,因为type==ExtensionFactory.class,所以ExtensionFactory的ExtensionLoader的objectFactory属性为null;
到这里先总结一下:
- 获取一个接口的扩展实现时,首先通过ExtensionLoader.getExtensionLoader(Class)获取一个ExtensionLoader加载器,每个SPI接口都有一个自己的ExtensionLoader(创建时放入缓存);
- 而ExtensionLoader是通过ExtensionFactory来加载的,ExtensionFactory也是一个SPI,它有两个实现:
- SpiExtensionFactory
- SpringExtensionFactory
- AdaptiveExtensionFactory
- ExtensionLoader.getExtensionLoader(ExtensionFactory.class)只会实例化一次,在之后有别的SPI接口创建时,不会再对它初始化,因为它已经初始化过了;
就是在加载一个实现时,是从Dubbo的SPI中加载还是Spring容器中加载;
3.SpiExtensionFactory与SpringExtensionFactory
前者是在dubbo的SPI体系(ExtensionLoader)中获取对象
后者是在SpringApplicationContext中获取对象;
在dubbo的IOC功能中injectExtension,注入依赖的对象是从哪个体系中查找;
2.2 getAdaptiveExtension
2.2.1 源码分析
源码接着上面的:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()中的getAdaptiveExtension()来说,在分析它之前,得先说明什么是AdaptiveExtension;
对于Dubbo的SPI接口如果没有编码实现
一个@Adaptive的实现类的话,Dubbo会自动为接口生成一个实现类;
- @Adaptive:如果加在实现类上的话,那么getAdaptiveExtension则返回该实现类;并且一个SPI接口只允许有一个Adaptive实现类;
- @Adaptive:如果加在接口方法上的话,那么Dubbo会生成一个实现类,会代理@Adaptive接口方法;
Adaptive实现类 ExtensionLoader#getAdaptiveExtension()
public T getAdaptiveExtension() {
// 从缓存中获取实例,从这里也可以看出,一个SPI接口只允许有一个Adative实现类;
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
synchronized (cachedAdaptiveInstance) {
// 这里做了个双重检查,加锁之后再次对它进行判断;
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
// 创建Adaptive实例
instance = createAdaptiveExtension();
// 将其添加到缓存
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
return (T) instance;
}
核心逻辑是在createAdaptiveExtension方法内:
private T createAdaptiveExtension() {
try {
// getAdaptiveExtensionClass 返回一个Class类型,之后调用该Class的newInstance生成实例;
// 而inject就是dubbo的IOC功能,它能实现对SPI接口中所依赖的对象进行注入;
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
接着先来看 getAdaptiveExtensionClass,且SPI有默认实现的Adaptive实现类的情况:;
缓存名称 | 含义 |
---|---|
cachedDefaultName | 接口SPI的Value,如果SPI(“A”)表示当前接口的Default实现是A |
cachedAdaptiveClass | 接口SPI的编码方式Adaptive实现类的clazz引用 |
cachedWrapperClasses | Set SPI接口的实现类构造方法中包含当前SPI类型的Set集合,AOP功能 |
cachedActivates | Map SPI实现类如果不满足cachedAdaptiveClass的情况下,会将key和activate注解存到这里 |
cachedNames | Map SPI实现类中非Adaptive实现类的实现,key=实现类clazz,value=实现类名称 |
extensionClasses | Map 作用与cachedNames一样,只是它的key=实现类名称,value=实现类clazz |
cachedInstances | Map 作用是存放非Adaptive实现的实例对象,key=name,value=Holder |
EXTENSION_INSTANCES | Map 作用是存放非Adaptive实现的实例对象,key=clazz,value=实例对象 |
private Class<?> getAdaptiveExtensionClass() {
// 加载当前SPI接口的实现类
getExtensionClasses();
// cachedAdaptiveClass = SPI的编码方式Adaptive实现类的clazz引用
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 如果当前SPI接口没有编码方式实现的Adaptive,则下面进行生成一个;
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
private Map<String, Class<?>> getExtensionClasses() {
// 首先从缓存中获取,如果没有,则通过loadExtensionClasses进行加载
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
// 这里做了个双重检查判断;
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
// 获取当前接口ExtensionFactory的SPI注解
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
// 如果该注解的value为值,并且包含,号,则解析报错:more than 1 default extension name on extension
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if (names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
// cachedDefaultName=SPI注解中的value
if (names.length == 1) cachedDefaultName = names[0];
}
}
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadDirectory(extensionClasses, DUBBO_DIRECTORY);
loadDirectory(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
// META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
// adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
// spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
// 这个路径里面存放的是SPI的实现类有哪些
// 这里并不是一次加载所有的SPI,而是只加载当前ExtensionFactory的SPI实现;
String fileName = dir + type.getName();
try {
Enumeration<java.net.URL> urls;
// 获取 ExtensionLoader.class.getClassLoader()
// 这个一般是指的应用类加载器 AppClassLoader;
ClassLoader classLoader = findClassLoader();
if (classLoader != null) {
// 加载资源
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while (urls.hasMoreElements()) {
// 通过classLoader.getResources得到的路径为:
// file:/xxx/dubbo/dubbo-common/target/classes/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
java.net.URL resourceURL = urls.nextElement();
// 加载资源
loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable t) {
logger.error("Exception when load extension class(interface: " +
type + ", description file: " + fileName + ").", t);
}
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));
try {
String line;
// 每次读一行
while ((line = reader.readLine()) != null) {
// 如果文件行内包含有#号,则先将其排除掉;
final int ci = line.indexOf('#');
if (ci >= 0) line = line.substring(0, ci);
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
// 通过=号截取出key和value,name表示是key,line表示的是value
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
// 先将 Class.forName(line, true, classLoader),将读到的实现类路径字符串转换Class类型;
// 加载Class;
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
}
} finally {
reader.close();
}
} catch (Throwable t) {
logger.error("Exception when load extension class(interface: " +
type + ", class file: " + resourceURL + ") in " + resourceURL, t);
}
}
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
// 判断clazz是否是type的子类;
// interface com.alibaba.dubbo.common.extension.ExtensionFactory是class com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory的父类
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + "is not subtype of interface.");
}
// ExtensionFactory的第一个实现类为AdaptiveExtensionFactory,而它的类上是有Adaptive注解的;
if (clazz.isAnnotationPresent(Adaptive.class)) {
// 如果包含,则将cachedAdaptiveClass设置为当前SPI接口的Adaptive实现类
if (cachedAdaptiveClass == null) {
cachedAdaptiveClass = clazz;
} else if (!cachedAdaptiveClass.equals(clazz)) {
throw new IllegalStateException("More than 1 adaptive class found: "
+ cachedAdaptiveClass.getClass().getName()
+ ", " + clazz.getClass().getName());
}
}
// 判断当前Adaptive实现类是否存在 当前SPI接口 ExtensionFactory的构造方法,如果有,则返回true;它的作用是做类似AOP,动态代理;在getExtension方法分析时会讲;
else if (isWrapperClass(clazz)) {
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} else {
// 获取一下它的无参构造器,如果没有,这里会报错,错误信息会传至上一层;
// 这也就是说,普通的SPI接口实现类,得提供无参构造器;
clazz.getConstructor();
// 如果SPI的文件中,配置的name为空,则会在这里生成一个;
if (name == null || name.length() == 0) {
name = findAnnotationName(clazz);
if (name.length() == 0) {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
}
}
// 从这里可以看出,一个SPI的实现在文件中可以配置多个name,用,号分隔即可;
String[] names = NAME_SEPARATOR.split(name);
if (names != null && names.length > 0) {
// 如果当前clazz包含Adaptive注解,但如果包含这个Adaptive会走第一个if,没太清楚为什么这里做这个判断???
Activate activate = clazz.getAnnotation(Activate.class);
if (activate != null) {
cachedActivates.put(names[0], activate);
}
// 将clazz和定义的key放到cachedNames和extensionClasses
// 做到通过key可找value,通过value可找key;
for (String n : names) {
if (!cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);
if (c == null) {
extensionClasses.put(n, clazz);
} else if (c != clazz) {
throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
}
}
}
}
}
SPI没有默认的Adaptive实现类的情况:;
我们从getAdaptiveExtensionClass中的createAdaptiveExtensionClass开始看起;
private Class<?> createAdaptiveExtensionClass() {
// 生成动态Adaptive的代码
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);
}
上面代码首先是拼装class内容,然后动态编译生成Class文件;动态生成的类文件如下:
@SPI("impl1")
public interface SimpleExt {
// @Adaptive example, do not specify a explicit key.
@Adaptive
String echo(URL url, String s);
@Adaptive({"key1", "key2"})
String yell(URL url, String s);
// no @Adaptive
String bang(URL url, int i);
}
public class SimpleExt$Adaptive implements com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt {
public java.lang.String bang(com.alibaba.dubbo.common.URL arg0, int arg1) {
throw new UnsupportedOperationException("method public abstract java.lang.String com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.bang(com.alibaba.dubbo.common.URL,int) of interface com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt is not adaptive method!");
}
public java.lang.String echo(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
String extName = url.getParameter("simple.ext", "impl1");
if (extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([simple.ext])");
com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
return extension.echo(arg0, arg1);
}
public java.lang.String yell(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
String extName = url.getParameter("key1", url.getParameter("key2", "impl1"));
if (extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([key1, key2])");
com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
return extension.yell(arg0, arg1);
}
}
比如上面的接口可以看到,生成的动态适配类只会重写接口中有@Adaptive注解的抽象方法,没有该注解的只是重写但方法体会抛异常;
再来看一看它所生成的动态适配类中的方法做了什么事;主要的是以下两行代码:
// 在运行时,可根据参数获取对应的SPI实现类
com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension =
(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
// 然后调用它的方法;
extension.echo(arg0, arg1);
dubbo为什么要生成这个动态适配类Adaptive呢?
如果没有这个动态适配类,那我们该如何通过不同的参数寻找一个具体的SPI接口的实现类呢?而有了生成的这个适配类,可以通过它,做一些条件的解析,查询出具体的实现类,通过调适配类的方式完成对最终实现类的调用;
URL的使用
public java.lang.String echo(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg0;
String extName = url.getParameter("simple.ext", "impl1");
if (extName == null)
throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([simple.ext])");
com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
return extension.echo(arg0, arg1);
}
观察它的URL匹配原则,它会从URL中获取simple.ext参数,如果未设置,则默认使用impl1,是因为SimpleExt的SPI(“impl1”)的默认值是它;
2.3 injectExtension
位置:com.alibaba.dubbo.common.extension.ExtensionLoader#injectExtension
它的作用类似于Spring的IOC,开篇我说了java的SPI是不支持IOC的;
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
// 如果有set开头的方法
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
/**
* Check {@link DisableInject} to see if we need auto injection for this property
*/
// 并且未禁用dubbo的IOC功能
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
Class<?> pt = method.getParameterTypes()[0];
try {
// 比如setExt(Ext2),这里得到的结果:ext2
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
// 然后拿 com.alibaba.dubbo.common.extensionloader.ext2.Ext2去AdaptiveExtensionFactory中查找,如果存在,则给set方法赋值;
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("fail to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
2.4 getExtension
在getExtension之前,前面对非Adaptive实现类获取的都是Clazz对象,而getExtension是真正的初始化这些对象;
public T getExtension(String name) {
// 首先进行参数校验
if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
// 如果传的name="true",则使用默认的实现类;其实就是cachedDefaultName所指的name,SPI("A")中的A值;
if ("true".equals(name)) {
return getDefaultExtension();
}
// cachedInstances是存放非Adaptive实现的实例对象,这里会将对象封装成一个Holder;
// 在获取时,任然是先查缓存,如果没有,则去实例化;
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<Object>());
holder = cachedInstances.get(name);
}
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
// 实例化对象;
instance = createExtension(name);
holder.set(instance);
}
}
}
return (T) instance;
}
private T createExtension(String name) {
// 通过name获取对应的Clazz对象
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
throw findException(name);
}
try {
// 非Adaptive实现的实例对象,key=clazz,value=实例对象
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
// 对clazz实例化
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 这里是熟悉的dubbo的IOC功能;
injectExtension(instance);
// 这是dubbo的AOP功能;
// cachedWrapperClasses存放的是,非Adaptive实现类中有 当前SPI类型的构造器;
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
for (Class<?> wrapperClass : wrapperClasses) {
// wrapperClass.getConstructor(type).newInstance(instance) 实例化这些Wrapper实现类,参数是当前name指定的实现类,其实就是通过Wrapper包装一层
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}
这里对dubbo的AOP增强做下说明:
比如:Protocol,它的实现中有三个Wrapper:
- ProtocolFilterWrapper
- ProtocolListenerWrapper
- QosProtocolWrapper
他们都有相似的地方是:
public QosProtocolWrapper(Protocol protocol) {
if (protocol == null) {
throw new IllegalArgumentException("protocol == null");
}
this.protocol = protocol;
}
构造方法中都有Protocol,这种在处理时会将它们加入到cachedWrapperClasses,而在使用Protocol的实现类时,这三个会进行实现类的功能增强;
2.5 Compiler SPI
在上面的com.alibaba.dubbo.common.extension.ExtensionLoader#createAdaptiveExtensionClass
位置跳过了这段代码,现在来分析一下它的作用;
com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
compiler.compile(code, classLoader);
首先确定Compiler是一个SPI,@SPI("javassist")
它的默认实现是javassist,它有一个编码实现的Adaptive实现类:AdaptiveCompiler
@Adaptive
public class AdaptiveCompiler implements Compiler {
private static volatile String DEFAULT_COMPILER;
public static void setDefaultCompiler(String compiler) {
DEFAULT_COMPILER = compiler;
}
@Override
public Class<?> compile(String code, ClassLoader classLoader) {
Compiler compiler;
// 获取Compiler的ExtensionLoader对象;
ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
// 如果没有调setDefaultCompiler方法,那么这里的DEFAULT_COMPILER是null
String name = DEFAULT_COMPILER; // copy reference
if (name != null && name.length() > 0) {
compiler = loader.getExtension(name);
} else {
// 默认的是javassist实现:JavassistCompiler
// 通过javassist动态编译成Class对象;
compiler = loader.getDefaultExtension();
}
return compiler.compile(code, classLoader);
}
}