Dubbo SPI 源码深入分析
Posted 董博士的大学室友
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo SPI 源码深入分析相关的知识,希望对你有一定的参考价值。
1.先看入口在哪里,我们加载自定义的扩展都会写这行代码,那么就从分析ExtensionLoader开始了
ExtensionLoader.getExtensionLoader(XXX.class).getExtension("diyExtension");
1.1 getExtensionLoader
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } // 缓存思想大量应用,先看这个ExtensionLoader是否创建过了,创建过的会放在chm里面 ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) {
//没创建过就创建,放到chm里面 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }
1.1.1 new ExtensionLoader 的时候,先判断你是不是在要ExtensionFactory的扩展点,如果不是的话,就去拿ExtensionFactory的自适应扩展点(这里有待进一步研究为何这个逻辑)然后赋值给objectFactory (ExtensionLoader(protocol) 的成员变量:private final ExtensionFactory objectFactory;)
private ExtensionLoader(Class<?> type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class)
.getAdaptiveExtension()); }
1.1.2
此时回到上层方法,我们走完了new ExtensionLoader得到了一个ExtensionLoader,这个ExtensionLoader里面,带着成员变量ExtensionFactory,其值是经过自适应处理的ExtensionFactory,然后把 这个ExtensionLoader放到了chm里面(为什么呢?比如我在1.1处ExtensionLoader.getExtensionLoader(XXX.class)的XXX处入参传的是Protocol入参,但是你给我的是ExtensionFactory 相关的扩展点,是不是我要个苹果 ,看起来你给了我香蕉?)
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); }
1.2 此时执行1.1处的 getExtension,这里,是根据传的我们自定义的名字,去一个chm找是否有,没有创建一个,放到chm里,再查出来把他返回
public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } if ("true".equals(name)) { return getDefaultExtension(); } Holder<Object> holder = getOrCreateHolder(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 Holder<Object> getOrCreateHolder(String name) {
//ExtensionLoader的成员变量 private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<>());
holder = cachedInstances.get(name);
}
return holder;
}
public class Holder<T> {
private volatile T value;
public void set(T value) {
this.value = value;
}
public T get() {
return value;
}
}
以上是关于Dubbo SPI 源码深入分析的主要内容,如果未能解决你的问题,请参考以下文章