Dubbo源码分析-SPI机制
本源码基于dubbo2.6.6
参考dubbo官网:dubbo官网SPI解读
dubbo的SPI使用
//加载SPI标签的类放到缓存中
ExtensionLoader<MySPIDemo> extensionLoader = ExtensionLoader.getExtensionLoader(MySPIDemo.class);
//获取SPI类
MySPIDemo mySPIDemo = extensionLoader.getExtension("method");
加载SPI的入口getExtensionLoader
如果存在缓存中从缓存取,如果不存在那么就new ExtensionLoader(type)放入缓存并且返回
@SuppressWarnings("unchecked")
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 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) {
//加入缓存
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
这个构造方法如果type不是ExtensionFactory那么objectFactory就是ExtensionFactory创建的自适应拓展类(略有点绕)
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
从缓存(Holder)cachedAdaptiveInstance获取自适应拓展的实例
没有就通过createAdaptiveExtension()创建实例
这里T是ExtensionFactory
记住2点:
- 取缓存。
没缓存,创建
@SuppressWarnings(“unchecked”)
public T getAdaptiveExtension() {//先从缓存Holder中取
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
//加锁判断
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
//创建自适应拓展类,放入缓存
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通过反射创建实例
1.getAdaptiveExtensionClass找寻自适应拓展类的class对象
2.反射创建实例
3.injectExtension???
@SuppressWarnings("unchecked")
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
获取自适应拓展类的字节码对象
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
获取所有的自适应拓展类
先从缓存取,缓存没有就加载
private Map<String, Class<?>> getExtensionClasses() {
//从holder里面取缓存
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 static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + “internal/”;
private static final String DUBBO_DIRECTORY = “META-INF/dubbo/”;
private static final String SERVICES_DIRECTORY = “META-INF/services/”;
private Map<String, Class<?>> loadExtensionClasses() {
//判断类是不是有SPI标签(ExtensionFactory)
//ExtensionLoader.getExtensionLoader(ExtensionFactory.class)
//type=ExtensionFactory 这个类是有SPI标签的
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation != null) {
//获取spi的属性值
String value = defaultAnnotation.value();
if ((value = value.trim()).length() > 0) {
//根据正则表达式切分("\\s*[,]+\\s*")
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));
}
//获取缓存的名称
if (names.length == 1) cachedDefaultName = names[0];
}
}
//加载放入Map中,只有普通类才会加入到map中,自适应类不会加载进去
Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadDirectory(extensionClasses, DUBBO_DIRECTORY);
loadDirectory(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}
加载指定路径下的文件名是type的
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
//获取路径下的指定名称的文件名,见下方的图
String fileName = dir + type.getName();
try {
Enumeration<java.net.URL> urls;
ClassLoader classLoader = findClassLoader();
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while (urls.hasMoreElements()) {
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);
}
}
我们看一下这个文件的内容除去注释并且加载class
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;
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
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 {
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.");
}
//是否有适应注解
if (clazz.isAnnotationPresent(Adaptive.class)) {
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());
}
//是否是wrapper类型(clazz是否有一个参数是type的构造方法)
//clazz=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
//type=com.alibaba.dubbo.common.extension.ExtensionFactory
} else if (isWrapperClass(clazz)) {
//将clazz放入缓存中
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} else {
//既不是warpper类也没有Adaptive注解
clazz.getConstructor();
//name=spring
if (name == null || name.length() == 0) {
//获取extension注解的value,如果没有就用小写的类名
name = findAnnotationName(clazz);
if (name.length() == 0) {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
}
}
String[] names = NAME_SEPARATOR.split(name);
if (names != null && names.length > 0) {
//如果不为空,那么获取activate注解
Activate activate = clazz.getAnnotation(Activate.class);
//如果有注解就放入缓存中
if (activate != null) {
cachedActivates.put(names[0], activate);
}
for (String n : names) {
//如果缓存的名字不存在那么放入缓存中
if (!cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
//再去缓存extensionClasses中找寻对应的字节码对象
Class<?> c = extensionClasses.get(n);
//如果不存在就把clazz放进缓存
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());
}
}
}
}
}
获取extension注解的value,如果没有就用小写的类名
@SuppressWarnings("deprecation")
private String findAnnotationName(Class<?> clazz) {
com.alibaba.dubbo.common.Extension extension = clazz.getAnnotation(com.alibaba.dubbo.common.Extension.class);
//获取extension注解的value,如果没有就用小写的类名
if (extension == null) {
String name = clazz.getSimpleName();
if (name.endsWith(type.getSimpleName())) {
name = name.substring(0, name.length() - type.getSimpleName().length());
}
return name.toLowerCase();
}
return extension.value();
}
getExtensionClasses(加载文件中的类)
获取自适应拓展类
injectExtension((T) getAdaptiveExtensionClass().newInstance());
最后ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()获取的自适应拓展类是AdaptiveExtensionFactory
ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(MySPIDemo.class);
ExtensionLoader
private final Class<?> type=MySPIDemo.class;
private final ExtensionFactory objectFactory=AdaptiveExtensionFactory;
分析完成
getExtensionLoader总结:
- 获取ExtensionLoader会先从EXTENSION_LOADERS缓存中取。
- 如果是ExtensionFactory类objectFactory对象创建工厂就是空,否则是ExtensionFactory的自适应拓展类
- 获取自适应拓展类,先查询缓存cachedAdaptiveInstance,获取自适应的实例,没有就创建拓展类
- 先获取字节码对象,再通过反射创建实例
- 先获取所有的拓展字节码对象,先从缓存cachedClasses取如果不存在loadExtensionClasses,并且加入缓存
- 获取type的SPI注解的值作为缓存cachedDefaultName,然后从不同的目录加载(DUBBO_INTERNAL_DIRECTORY、DUBBO_DIRECTORY、SERVICES_DIRECTORY)
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + “internal/”;
private static final String DUBBO_DIRECTORY = “META-INF/dubbo/”;
private static final String SERVICES_DIRECTORY = “META-INF/services/”; - 通过文件路径去加载资源loadResource并且放入缓存extensionClasses
- loadClass,如果类上有Adaptive注解,放入缓存(Class类自适应拓展字节码类)cachedAdaptiveClass
- 如果类是wrapper类,构造函数有一个type类型的入参。将字节码对象放入cachedWrapperClasses缓存
- 如果类是一个普通类 ,判断有没有Activate注解,如果有的话,name不为空就把name作为key,如果name为空把extension注解的value,如果没有就用小写的类名作为key(name),Activate作为值放入缓存cachedActivates中。
- 如果没有Activate注解将字节码对象作为key,name作为value放入缓存cachedNames,查询缓存extensionClasses中是否有name对应的字节码对象,如果不存在就放进去。
缓存类
- EXTENSION_LOADERS(ConcurrentMap
, ExtensionLoader<?>>)缓存,拓展加载类缓存 - cachedAdaptiveInstance(Holder)自适应拓展类实例缓存
- cachedClasses(Holder
- cachedAdaptiveClass(Class<?>)缓存拓展类的字节码对象
- cachedWrapperClasses(ConcurrentHashSet
>)缓存wrapper对象 - cachedActivates(Map
)缓存Activate - cachedNames(ConcurrentMap
, String>)缓存字节码对象和名称
接下来分析
MySPIDemo mySPIDemo = extensionLoader.getExtension(“method”);
@SuppressWarnings("unchecked")
public T getExtension(String name) {
if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
//从缓存cachedInstances(ConcurrentMap<String, Holder<Object>>)中获取该名称的Holder
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
//将对象放入缓存,取出来放入holder
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;
}
Dubbo IOC
Dubbo IOC 是通过 setter 方法注入依赖。Dubbo 首先会通过反射获取到实例的所有方法,然后再遍历方法列表,检测方法名是否具有 setter 方法特征。若有,则通过 ObjectFactory 获取依赖对象,最后通过反射调用 setter 方法将依赖设置到目标对象中。整个过程对应的代码如下:
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
if (method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers())) {
//这个方法可不可以进行反射
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
//获取参数类型
Class<?> pt = method.getParameterTypes()[0];
try {
//获取set后的参数名称:比如setAge,那么property=age;
String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
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;
}
objectFactory.getExtension有3种实现方式
通过SPI获取
public class SpiExtensionFactory implements ExtensionFactory {
@Override
public <T> T getExtension(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension();
}
}
return null;
}
}
还没有评论,来说两句吧...