Dubbo SPI组件加载流程源码分析

        本文以加载com.alibaba.dubbo.rpc.Protocol SPI组件为例予以分析:

可用代码

ExtensionLoader<Protocol> extensionLoader = ExtensionLoader
		.getExtensionLoader(Protocol.class);
for (String name : extensionLoader.getSupportedExtensions()) {
	Protocol protocol = extensionLoader.getExtension(name);
	// do something
}

关键步骤源码

获取ExtensionLoader

/** ExtensionLoader.java */
ExtensionLoader<Protocol> extensionLoader = ExtensionLoader.getExtensionLoader(Protocol.class);

// 提供getExtensionLoader static方法获取
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!");
	}
	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;
}

private ExtensionLoader(Class<?> type) {
	this.type = type;
	// 非ExtensionFactory.class获取ExtensionFactory的Adaptive Extension Object
	objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

// 获取Adaptive Extension实例
public T getAdaptiveExtension() {
	Object instance = cachedAdaptiveInstance.get();
	if (instance == null) {
		if(createAdaptiveInstanceError == null) {
			synchronized (cachedAdaptiveInstance) {
				instance = cachedAdaptiveInstance.get();
				if (instance == null) {
					try {
						// cachedAdaptiveInstance无缓存,则创建
						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);
		}
	}
	
// 创建Adaptive Extension Object
private T createAdaptiveExtension() {
	try {
		return injectExtension((T) getAdaptiveExtensionClass().newInstance());
	} catch (Exception e) {
		throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);
	}
}

// 获取Adaptive Extension Class
private Class<?> getAdaptiveExtensionClass() {
	// 从WEB-INF\lib\*.jar中的META-INF/dubbo/、META-INF/services/、META-INF/dubbo/internal/路径读取组件Class文件中的key-value
	getExtensionClasses();
	if (cachedAdaptiveClass != null) {
		return cachedAdaptiveClass;
	}
	// 没有组件默认的Adaptive Class,则自行生成
	return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

private Map<String, Class<?>> getExtensionClasses() {
	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() {
	final SPI defaultAnnotation = type.getAnnotation(SPI.class);
	if(defaultAnnotation != null) {
		String value = defaultAnnotation.value();
		if(value != null && (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));
			}
			if(names.length == 1) cachedDefaultName = names[0];
		}
	}

	Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
	// 从WEB-INF\lib\*.jar中的META-INF/dubbo/、META-INF/services/、META-INF/dubbo/internal/路径读取组件com.alibaba.dubbo.rpc.Protocol文件
	// 内容为key-value形式,如:registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
	loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
	loadFile(extensionClasses, DUBBO_DIRECTORY);
	loadFile(extensionClasses, SERVICES_DIRECTORY);
	return extensionClasses;
}

// 用ClassLoader加载组件com.alibaba.dubbo.rpc.Protocol文件
private void loadFile(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 url = urls.nextElement();
				try {
					BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
					try {
						String line = null;
						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) {
										Class<?> clazz = Class.forName(line, true, classLoader);
										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)) {
											//	缓存组件默认的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());
											}
										} else {
											try {
												clazz.getConstructor(type);
												Set<Class<?>> wrappers = cachedWrapperClasses;
												if (wrappers == null) {
													cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
													wrappers = cachedWrapperClasses;
												}
												// 缓存组件的Wrap Class
												wrappers.add(clazz);
											} catch (NoSuchMethodException e) {
												clazz.getConstructor();
												if (name == null || name.length() == 0) {
													name = findAnnotationName(clazz);
													if (name == null || name.length() == 0) {
														if (clazz.getSimpleName().length() > type.getSimpleName().length()
																&& clazz.getSimpleName().endsWith(type.getSimpleName())) {
															name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
														} else {
															throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
														}
													}
												}
												String[] names = NAME_SEPARATOR.split(name);
												if (names != null && names.length > 0) {
													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);
														}
														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());
														}
													}
												}
											}
										}
									}
								} catch (Throwable t) {
									IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
									exceptions.put(line, e);
								}
							}
						} // end of while read lines
					} finally {
						reader.close();
					}
				} catch (Throwable t) {
					logger.error("Exception when load extension class(interface: " +
										type + ", class file: " + url + ") in " + url, t);
				}
			} // end of while urls
		}
	} catch (Throwable t) {
		logger.error("Exception when load extension class(interface: " +
				type + ", description file: " + fileName + ").", t);
	}
}

// 自行生成且编译Adaptive Extension Class
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);
}

private String createAdaptiveExtensionClassCode() {
	StringBuilder codeBuidler = new StringBuilder();
	Method[] methods = type.getMethods();
	boolean hasAdaptiveAnnotation = false;
	for(Method m : methods) {
		if(m.isAnnotationPresent(Adaptive.class)) {
			hasAdaptiveAnnotation = true;
			break;
		}
	}
	// 完全没有Adaptive方法,则不需要生成Adaptive类
	if(! hasAdaptiveAnnotation)
		throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!");

	codeBuidler.append("package " + type.getPackage().getName() + ";");
	codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";");
	codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adpative" + " implements " + type.getCanonicalName() + " {");

	for (Method method : methods) {
		Class<?> rt = method.getReturnType();
		Class<?>[] pts = method.getParameterTypes();
		Class<?>[] ets = method.getExceptionTypes();

		Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
		StringBuilder code = new StringBuilder(512);
		if (adaptiveAnnotation == null) {
			code.append("throw new UnsupportedOperationException(\"method ")
					.append(method.toString()).append(" of interface ")
					.append(type.getName()).append(" is not adaptive method!\");");
		} else {
			int urlTypeIndex = -1;
			for (int i = 0; i < pts.length; ++i) {
				if (pts[i].equals(URL.class)) {
					urlTypeIndex = i;
					break;
				}
			}
			// 有类型为URL的参数
			if (urlTypeIndex != -1) {
				// Null Point check
				String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");",
								urlTypeIndex);
				code.append(s);

				s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex);
				code.append(s);
			}
			// 参数没有URL类型
			else {
				String attribMethod = null;

				// 找到参数的URL属性
				LBL_PTS:
				for (int i = 0; i < pts.length; ++i) {
					Method[] ms = pts[i].getMethods();
					for (Method m : ms) {
						String name = m.getName();
						if ((name.startsWith("get") || name.length() > 3)
								&& Modifier.isPublic(m.getModifiers())
								&& !Modifier.isStatic(m.getModifiers())
								&& m.getParameterTypes().length == 0
								&& m.getReturnType() == URL.class) {
							urlTypeIndex = i;
							attribMethod = name;
							break LBL_PTS;
						}
					}
				}
				if(attribMethod == null) {
					throw new IllegalStateException("fail to create adative class for interface " + type.getName()
							+ ": not found url parameter or url attribute in parameters of method " + method.getName());
				}

				// Null point check
				String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");",
								urlTypeIndex, pts[urlTypeIndex].getName());
				code.append(s);
				s = String.format("\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");",
								urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod);
				code.append(s);

				s = String.format("%s url = arg%d.%s();",URL.class.getName(), urlTypeIndex, attribMethod);
				code.append(s);
			}

			String[] value = adaptiveAnnotation.value();
			// 没有设置Key,则使用“扩展点接口名的点分隔 作为Key
			if(value.length == 0) {
				char[] charArray = type.getSimpleName().toCharArray();
				StringBuilder sb = new StringBuilder(128);
				for (int i = 0; i < charArray.length; i++) {
					if(Character.isUpperCase(charArray[i])) {
						if(i != 0) {
							sb.append(".");
						}
						sb.append(Character.toLowerCase(charArray[i]));
					}
					else {
						sb.append(charArray[i]);
					}
				}
				value = new String[] {sb.toString()};
			}

			boolean hasInvocation = false;
			for (int i = 0; i < pts.length; ++i) {
				if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) {
					// Null Point check
					String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i);
					code.append(s);
					s = String.format("\nString methodName = arg%d.getMethodName();", i);
					code.append(s);
					hasInvocation = true;
					break;
				}
			}

			String defaultExtName = cachedDefaultName;
			String getNameCode = null;
			for (int i = value.length - 1; i >= 0; --i) {
				if(i == value.length - 1) {
					if(null != defaultExtName) {
						if(!"protocol".equals(value[i]))
							if (hasInvocation)
								getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
							else
								getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
						else
							getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);
					}
					else {
						if(!"protocol".equals(value[i]))
							if (hasInvocation)
								getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
							else
								getNameCode = String.format("url.getParameter(\"%s\")", value[i]);
						else
							getNameCode = "url.getProtocol()";
					}
				}
				else {
					if(!"protocol".equals(value[i]))
						if (hasInvocation)
							getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
						else
							getNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);
					else
						getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);
				}
			}
			code.append("\nString extName = ").append(getNameCode).append(";");
			// check extName == null?
			String s = String.format("\nif(extName == null) " +
					"throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");",
					type.getName(), Arrays.toString(value));
			code.append(s);

			s = String.format("\n%s extension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",
					type.getName(), ExtensionLoader.class.getSimpleName(), type.getName());
			code.append(s);

			// return statement
			if (!rt.equals(void.class)) {
				code.append("\nreturn ");
			}

			s = String.format("extension.%s(", method.getName());
			code.append(s);
			for (int i = 0; i < pts.length; i++) {
				if (i != 0)
					code.append(", ");
				code.append("arg").append(i);
			}
			code.append(");");
		}

		codeBuidler.append("\npublic " + rt.getCanonicalName() + " " + method.getName() + "(");
		for (int i = 0; i < pts.length; i ++) {
			if (i > 0) {
				codeBuidler.append(", ");
			}
			codeBuidler.append(pts[i].getCanonicalName());
			codeBuidler.append(" ");
			codeBuidler.append("arg" + i);
		}
		codeBuidler.append(")");
		if (ets.length > 0) {
			codeBuidler.append(" throws ");
			for (int i = 0; i < ets.length; i ++) {
				if (i > 0) {
					codeBuidler.append(", ");
				}
				codeBuidler.append(ets[i].getCanonicalName());
			}
		}
		codeBuidler.append(" {");
		codeBuidler.append(code.toString());
		codeBuidler.append("\n}");
	}
	codeBuidler.append("\n}");
	if (logger.isDebugEnabled()) {
		logger.debug(codeBuidler.toString());
	}
	return codeBuidler.toString();
}

获取所有缓存的com.alibaba.dubbo.rpc.Protocol组件

/** ExtensionLoader.java */
public Set<String> getSupportedExtensions() {
	Map<String, Class<?>> clazzes = getExtensionClasses();
	return Collections.unmodifiableSet(new TreeSet<String>(clazzes.keySet()));
}

获取com.alibaba.dubbo.rpc.Protocol扩展组件实例

/** ExtensionLoader.java */
/**
 * 返回指定名字的扩展。如果指定名字的扩展不存在,则抛异常 {@link IllegalStateException}.
 *
 * @param name
 * @return
 */
@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();
	}
	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) {
				// 创建com.alibaba.dubbo.rpc.Protocol扩展组件实例,且缓存
				instance = createExtension(name);
				holder.set(instance);
			}
		}
	}
	return (T) instance;
}

// 创建com.alibaba.dubbo.rpc.Protocol扩展组件实例
private T createExtension(String name) {
	// 获取com.alibaba.dubbo.rpc.Protocol扩展组件Class
	Class<?> clazz = getExtensionClasses().get(name);
	if (clazz == null) {
		throw findException(name);
	}
	try {
		T instance = (T) EXTENSION_INSTANCES.get(clazz);
		if (instance == null) {
			EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
			instance = (T) EXTENSION_INSTANCES.get(clazz);
		}
		// 扩展组件实例依赖注入
		injectExtension(instance);
		Set<Class<?>> wrapperClasses = cachedWrapperClasses;
		// 用cachedWrapperClasses Wrap扩展组件实例
		if (wrapperClasses != null && wrapperClasses.size() > 0) {
			for (Class<?> wrapperClass : wrapperClasses) {
				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);
	}
}

      通过源码分析,可以了解SPI组件加载流程,掌握如何扩展SPI组件。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值