在上一篇文章Dubbo进阶(六):Dubbo扩展点加载机制(中)中介绍了扩展点机制的一些注解,这篇文章主要通过源码来学习一下ExtensionLoader
的原理。ExtensionLoader
是整个扩展机制的主要逻辑,在这个类里实现了配置的加载、扩展类缓存、自适应对象生成等所有工作。
ExtensionLoader的工作流程
ExtensionLoader的逻辑入口可以分为getExtension
、getAdaptiveExtension
和getActivateExtension
三个,分别是获取普通扩展类、获取自动适应扩展类和获取自动激活扩展类。
getExtension的实现原理
// 根据name获取扩展点实现的实例
public T getExtension(String name) {
// 如果没有给出指定的name,抛出异常
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
// 如果name=true,则返回默认的扩展类
if ("true".equals(name)) {
// 详细逻辑请看下面第二段代码块
return getDefaultExtension();
}
// 获取扩展对象,Holder里的value属性保存着扩展对象实例
final 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;
}
---------------------第二段代码块,华丽丽的分割线------------------------
接下来是获取默认extension
的逻辑。
public T getDefaultExtension() {
// 加载默认
getExtensionClasses();
if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
return null;
}
return getExtension(cachedDefaultName);
}
private Map<String, Class<?>> getExtensionClasses() {
// 尝试先从缓存中获取classes
Map<String, Class<?>> classes = cachedClasses.get();
// 如果缓存中没有,则开始加载class
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
// 检查是否有@SPI注解,如果有则获取注解中的名字并缓存为默认的实现。
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
for (LoadingStrategy strategy : strategies) {
// 加载配置文件
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
// 由于 Dubbo 迁到 apache ,所以包名有变化,会替换之前的 alibaba 为 apache
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.excludedPackages());
}
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type,
boolean extensionLoaderClassLoaderFirst, String... excludedPackages) {
// 获取文件在项目中的路径,如:META-INF/dubbo/top.ytao.demo.spi.AnimalService
String fileName = dir + type;
try {
Enumeration<java.net.URL> urls = null;
ClassLoader classLoader = findClassLoader();
// 加载内部扩展类
if (extensionLoaderClassLoaderFirst) {
ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
urls = extensionLoaderClassLoader.getResources(fileName);
}
}
// 加载当前 fileName 文件
if(urls == null || !urls.hasMoreElements()) {
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, excludedPackages);
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " +
type + ", description file: " + fileName + ").", t);
}
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
java.net.URL resourceURL, String... excludedPackages) {
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
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('=');
// 如果当前行存在 "=",将 "=" 左右的值分开复制给 name 和 line
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
// 加载扩展类
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);
}
}
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading 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 {
// 检查当前实现类是否实现了 type 接口
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error occurred when loading extension class (interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + " is not subtype of interface.");
}
// 当前实现类是否有 Adaptive 注解
if (clazz.isAnnotationPresent(Adaptive.class)) {
cacheAdaptiveClass(clazz);
// 当前类是否为 Wrapper 包装扩展类
} else if (isWrapperClass(clazz)) {
cacheWrapperClass(clazz);
} else {
// 尝试当前类是否有无参构造方法
clazz.getConstructor();
if (StringUtils.isEmpty(name)) {
// 如果 name 为空,则获取 clazz 的 @Extension 注解的值,如果注解值也没有,则使用小写类名
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 (ArrayUtils.isNotEmpty(names)) {
// 缓存 扩展名和@Activate的缓存
cacheActivateClass(clazz, names[0]);
for (String n : names) {
cacheName(clazz, n);
// 将 扩展类和扩展名 保存到extensionClasses 扩展名->扩展类 关系映射中
saveInExtensionClass(extensionClasses, clazz, n);
}
}
}
}
---------------------第二段代码块,华丽丽的分割线------------------------
---------------------第三段代码块,华丽丽的分割线------------------------
创建扩展对象的逻辑如下
private T createExtension(String name) {
// 从全部扩展类中,获取当前扩展名对应的扩展类
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, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
// 向当前实例注入依赖
injectExtension(instance);
// 获取包装扩展类缓存
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
// 创建包装扩展类实例,并向其注入依赖
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
// 初始化扩展对象
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " +
type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
依赖注入的实现
private T injectExtension(T instance) {
if (objectFactory == null) {
return instance;
}
try {
// 遍历当前扩展类的全部方法,如果当前方法不属于 setter 方法,
// 即不是以 'set'开头的方法名,参数不是一个的,该方法访问级别不是 public 的,则不往下执行
for (Method method : instance.getClass().getMethods()) {
if (!isSetter(method)) {
continue;
}
/**
* Check {@link DisableInject} to see if we need auto injection for this property
*/
// 当前方法是否添加了不要注入依赖的注解
if (method.getAnnotation(DisableInject.class) != null) {
continue;
}
Class<?> pt = method.getParameterTypes()[0];
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
// 通过属性 setter 方法获取属性名
String property = getSetterProperty(method);
// 获取依赖对象
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
// 设置依赖
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error("Failed to inject via method " + method.getName()
+ " of interface " + type.getName() + ": " + e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return instance;
}
---------------------第三段代码块,华丽丽的分割线------------------------
getAdaptiveExtension的实现原理
public T getAdaptiveExtension() {
// 获取实例化对象缓存
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " +
createAdaptiveInstanceError.toString(),
createAdaptiveInstanceError);
}
// 双重检查锁后创建自适应扩展
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
// 创建自适应扩展
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
private T createAdaptiveExtension() {
try {
// 获取自适应扩展后,注入依赖
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
private Class<?> getAdaptiveExtensionClass() {
// 加载全部扩展类
getExtensionClasses();
// 加载全部扩展类后,如果有 @Adaptive 标注的类,cachedAdaptiveClass 则一定不会为空
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 创建自适应扩展类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
private Class<?> createAdaptiveExtensionClass() {
// 生成自适应扩展代码
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
// 获取扩展类加载器
ClassLoader classLoader = findClassLoader();
// 获取编译器类型的实现类
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
// 编译代码,返回该对象
return compiler.compile(code, classLoader);
}
getActivateExtension的实现原理
public List<T> getActivateExtension(URL url, String[] values, String group) {
List<T> activateExtensions = new ArrayList<>();
List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);
if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {
// 获取所有扩展类
getExtensionClasses();
// 遍历所有@Active注解对象
for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
//spi 扩展名
String name = entry.getKey();
Object activate = entry.getValue();
String[] activateGroup, activateValue;
if (activate instanceof Activate) {
activateGroup = ((Activate) activate).group();
activateValue = ((Activate) activate).value();
} else if (activate instanceof com.alibaba.dubbo.common.extension.Activate) {
activateGroup = ((com.alibaba.dubbo.common.extension.Activate) activate).group();
activateValue = ((com.alibaba.dubbo.common.extension.Activate) activate).value();
} else {
continue;
}
//如果有group匹配
if (isMatchGroup(group, activateGroup)
&& !names.contains(name)
&& !names.contains(REMOVE_VALUE_PREFIX + name)
&& isActive(activateValue, url)) {
// 向集合里添加
activateExtensions.add(getExtension(name));
}
}
// 排序Activate 具体实现在ActivateComparator里,实现了Comparator 接口compare方法
activateExtensions.sort(ActivateComparator.COMPARATOR);
}
List<T> loadedExtensions = new ArrayList<>();
for (int i = 0; i < names.size(); i++) {
String name = names.get(i);
if (!name.startsWith(REMOVE_VALUE_PREFIX)
&& !names.contains(REMOVE_VALUE_PREFIX + name)) {
//遍历所有没有排除的扩展名
if (DEFAULT_KEY.equals(name)) {
if (!loadedExtensions.isEmpty()) {
activateExtensions.addAll(0, loadedExtensions);
loadedExtensions.clear();
}
} else {
//通过扩展名,加载扩展添加到结果集
loadedExtensions.add(getExtension(name));
}
}
}
if (!loadedExtensions.isEmpty()) {
activateExtensions.addAll(loadedExtensions);
}
// 返回符合条件的扩展类
return activateExtensions;
}