6.1 普通扩展对象的加载与创建
分析 ExtensionLoader 类型的 getExtension(String name) 方法,通过自适应扩展的铺垫,这里理解起来就更容易了
getExtension 是根据扩展名字获取具体扩展的通用方法,下面以某个类型来获取扩展进行举例
ApplicationModel 中获取配置管理器对象
configManager = (ConfigManager) this.getExtensionLoader(ApplicationExt.class).getExtension(ConfigManager.NAME);
6.1.1 getExtension 源码
先看下 ExtensionLoader#getExtension 方法源码,根据扩展名字查询扩展对象
public T getExtension(String name) {
// 传入参数 wrap 为 true
T extension = getExtension(name, true);
if (extension == null) {
throw new IllegalArgumentException("Not find extension: " + name);
}
return extension;
}
@SuppressWarnings("unchecked")
public T getExtension(String name, boolean wrap) {
// 检查扩展加载器是否已被销毁
checkDestroyed();
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
// 扩展名字为 true 则加载默认扩展
if ("true".equals(name)) {
return getDefaultExtension();
}
String cacheKey = name;
// 非 wrap 类型则将缓存的扩展名字 key 加上 _origin 后缀
// wrap 属于 aop 机制,俗称切面
// 这个 origin 在 aop 里面可以称为切点,下面的 wrap 扩展可以称为增强通知的类型,普通扩展和 wrap 扩展的扩展名字是一样的
if (!wrap) {
cacheKey += "_origin";
}
// 从 cachedInstances 缓存中查询
final Holder<Object> holder = getOrCreateHolder(cacheKey);
Object instance = holder.get();
// 缓存中不存在则创建扩展对象 双重校验锁
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
instance = createExtension(name, wrap);
holder.set(instance);
}
}
}
return (T) instance;
}
先着手来看下默认扩展的加载代码:
public T getDefaultExtension() {
// 加载扩展类型对应的所有扩展 SPI 实现类型
// 在加载所有扩展实现类型的时候会缓存这个扩展的默认实现类型,将对象缓存在 cachedDefaultName 中
getExtensionClasses();
if (StringUtils.isBlank(cachedDefaultName) || "true".equals(cachedDefaultName)) {
return null;
}
// 再回到加载扩展的方法
return getExtension(cachedDefaultName);
}
创建扩展对象 ExtensionLoader#createExtension 方法和自适应扩展的创建过程类似,具体过程如下:
- 加载扩展类型:getExtensionClasses
- 创建扩展对象:createExtensionInstance(clazz)
- 注入自适应扩展:injectExtension(instance)
- wrapper 包装处理
private T createExtension(String name, boolean wrap) {
// 扩展的创建的第一步扫描所有 jar 中的扩展实现,扫描完之后获取对应名字的扩展实现 Class 对象
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null || unacceptableExceptions.contains(name)) {
// 出现异常,转换异常信息以后再抛出
throw findException(name);
}
try {
// 当前扩展对象是否已经创建过了则直接从缓存中获取
T instance = (T) extensionInstances.get(clazz);
if (instance == null) {
// 第一次获取缓存中肯定没有则创建扩展对象然后缓存起来
extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
instance = (T) extensionInstances.get(clazz);
instance = postProcessBeforeInitialization(instance, name);
// 注入自适应扩展方法的自适应扩展对象,该方法前面讲自适应扩展时候说了
injectExtension(instance);
instance = postProcessAfterInitialization(instance, name);
}
// 是否开启了 wrap -> Dubbo 通过 Wrapper 实现 AOP
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
// wrap 类型排序 这个 wrap 类型是如何来的呢
// 在前面扫描扩展类型时,若当前扩展类型不是 Adaptive 注解修饰的,并且当前类型 type 有个构造器参数是 type 自身的
// 也是在前面加载扩展类型时说的装饰器模式,可以参考 DubboProtocol 构造器
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
// 根据 Wrapper 注解 order 值来进行排序值越小越在列表的前面
wrapperClassesList.sort(WrapperComparator.COMPARATOR);
// 反转之后值越大就会在列表的前面
Collections.reverse(wrapperClassesList);
}
// 从缓存中查到了 wrapper 扩展则遍历这些 wrapper 扩展进行筛选
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
for (Class<?> wrapperClass : wrapperClassesList) {
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
// 需要包装的扩展名。当此数组为空时,默认值为匹配
// wrapper 注解不存在或者 matches 匹配,或者 mismatches 不包含当前扩展
// 若匹配到了说明当前扩展对象需要进行 wrapper,就创建 wrapper 扩展对象后进行包装
boolean match = (wrapper == null)
|| ((ArrayUtils.isEmpty(wrapper.matches())
|| ArrayUtils.contains(wrapper.matches(), name))
&& !ArrayUtils.contains(wrapper.mismatches(), name));
if (match) {
// 一旦匹配就创建所有 wrapper 类型对象,同时将构造器参数设置为当前类型
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
instance = postProcessAfterInitialization(instance, name);
}
}
}
}
// Warning: After an instance of Lifecycle is wrapped by cachedWrapperClasses,
// it may not still be Lifecycle instance, this application may not invoke the lifecycle.initialize hook.
// 初始化扩展,如果当前扩展是 Lifecycle 类型则调用初始化方法
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException(
"Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: "
+ t.getMessage(),
t);
}
}
6.1.2 创建扩展对象
前面加载扩展类型在自适应扩展 ExtensionLoader#createAdaptiveExtension 方法已经说过了,这里具体来看下扩展对象的方法创建过程:createExtensionInstance
前面创建自适应扩展对象时仅仅是使用反射 newInstance 操作,而创建普通的扩展对象过程就相对复杂一点,接下来看下 ExtensionLoader#createExtensionInstance 方法
private Object createExtensionInstance(Class<?> type) throws ReflectiveOperationException {
// 在 ExtensionLoader 构造器中,有个 initInstantiationStrategy 方法中 new 了一个初始化策略 InstantiationStrategy 类型对象
return instantiationStrategy.instantiate(type);
}
实例化对象方法:InstantiationStrategy#instantiate
public <T> T instantiate(Class<T> type) throws ReflectiveOperationException {
// should not use default constructor directly, maybe also has another constructor matched scope model arguments
// 1. try to get default constructor
Constructor<T> defaultConstructor = null;
try {
// 反射获取对应类型的无参构造器
defaultConstructor = type.getConstructor();
} catch (NoSuchMethodException e) {
// ignore no default constructor
}
// 2. use matched constructor if found
List<Constructor<?>> matchedConstructors = new ArrayList<>();
// 获取所有构造器
Constructor<?>[] declaredConstructors = type.getConstructors();
for (Constructor<?> constructor : declaredConstructors) {
// 校验构造器参数类型是否为 ScopeModel 类型,若为 ScopeModel 则是匹配的构造器
// 说明扩展类型在这个版本想要让这个构造器生效,参数类型必须为 ScopeModel
if (isMatched(constructor)) {
matchedConstructors.add(constructor);
}
}
// remove default constructor from matchedConstructors
if (defaultConstructor != null) {
matchedConstructors.remove(defaultConstructor);
}
/*
match order:
1. the only matched constructor with parameters
2. default constructor if absent
*/
Constructor<?> targetConstructor;
// 匹配的参数 ScopeModel 构造器太多了就抛出异常
if (matchedConstructors.size() > 1) {
throw new IllegalArgumentException("Expect only one but found " + matchedConstructors.size()
+ " matched constructors for type: " + type.getName() + ", matched constructors: "
+ matchedConstructors);
// 一个参数一般为一个参数类型 ScopeModel 构造器
} else if (matchedConstructors.size() == 1) {
targetConstructor = matchedConstructors.get(0);
// 如果没有自定义构造器则使用空参数构造器
} else if (defaultConstructor != null) {
targetConstructor = defaultConstructor;
} else {
// 没有自定义构造器,抛出异常
throw new IllegalArgumentException("None matched constructor was found for type: " + type.getName());
}
// create instance with arguments
// 反射获取构造器参数的参数类型列表
Class<?>[] parameterTypes = targetConstructor.getParameterTypes();
Object[] args = new Object[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
// 借助 scopeModelAccessor 工具获取参数类型,这个参数类型为当前的域模型对象
args[i] = getArgumentValueForType(parameterTypes[i]);
}
return (T) targetConstructor.newInstance(args);
}
6.2 Wrap 机制
6.2.1 Wrapper 机制说明
Dubbo 通过 Wrapper 实现 AOP,Wrapper 机制,即扩展点自动包装
Wrapper 类同样实现了扩展点接口,但是 Wrapper 不是扩展点的真正实现。其用途主要是用于从 ExtensionLoader 返回扩展点时,包装在真正的扩展点实现类。
从 ExtensionLoader 中返回的实际上是 Wrapper 类的实例,Wrapper 持有了实际的扩展点实现类
扩展点的 Wrapper 类可以有多个,也可以按照需要进行新增。通过 Wrapper 类可以将所有扩展点公共逻辑迁移至 Wrapper 中,新加的 Wrapper 在所有的扩展点上添加了逻辑,有些类似 AOP,即 Wrapper 代理了扩展点
Wrapper 规范 Wrapper 机制不是通过注解实现的,而是通过一套 Wrapper 规范实现的,Wrapper 类在定义时要遵循如下规范:
- 类要实现 SPI 接口
- 类中要持有 SPI 接口的引用
- 类中必须含有一个带参的构造方法且参数只能有一个类型为 SPI 接口
- 在接口实现方法中要调用 SPI 接口引用对象的相应方法
- 类名称以 Wrapper 结尾
比如有如下几个扩展类型:
class org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
class org.apache.dubbo.qos.protocol.QosProtocolWrapper
class org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper
class org.apache.dubbo.qos.protocol.QosProtocolWrapper
6.2.2 扫描 Wrapper 类型
回顾下 Wrapper 扩展类型的扫描用于对象的创建,Wrapper 类型的扫描代码(来自 5.2.3 小节的 ExtensionLoader#loadClass 方法)如下:
if (clazz.isAnnotationPresent(Adaptive.class)) {
cacheAdaptiveClass(clazz, overridden);
// 扩展子类型构造器中是否有这个类型的接口 (这个可以想象下我们了解的 Java IO 流中的类型使用到的装饰器模式 构造器传个类型)
} else if (isWrapperClass(clazz)) {
cacheWrapperClass(clazz);
} else {
// Activate 类型扫描
}
isWrapperClass 方法通过判断构造器类型是否将当前类型标识为 Wrapper 类型
protected boolean isWrapperClass(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
// 参数类型只有一个,并且参数类型 = 当前 SPI 接口类型
if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0] == type) {
return true;
}
}
return false;
}
若当前类型满足 Wrapper 条件,将其追加到 ExtensionLoader cachedWrapperClasses 集合元素中
6.2.3 创建 Wrapper 类型
将 6.1.1 小节分析到的 ExtensionLoader#createExtension 方法部分代码截取过来
ExtensionLoader#getExtension 方法获取扩展对象时,会查询扩展对象是否有对应的 Wrapper 类型可扩展,再为其创建 Wrapper 扩展对象,如下代码所示:
// 是否开启了wrap -> Dubbo 通过 Wrapper 实现 AOP
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
// wrap 类型排序 这个 wrap 类型是如何来的呢
// 在前面扫描扩展类型时,若当前扩展类型不是 Adaptive 注解修饰的,并且当前类型 type 有个构造器参数是 type 自身的
// 也是在前面加载扩展类型时说的装饰器模式,可以参考 DubboProtocol 构造器
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
// 根据 Wrapper 注解 order 值来进行排序值越小越在列表的前面
wrapperClassesList.sort(WrapperComparator.COMPARATOR);
// 反转之后值越大就会在列表的前面
Collections.reverse(wrapperClassesList);
}
// 从缓存中查到了 wrapper 扩展则遍历这些 wrapper 扩展进行筛选
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
for (Class<?> wrapperClass : wrapperClassesList) {
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
// 需要包装的扩展名。当此数组为空时,默认值为匹配
// wrapper 注解不存在或者 matches 匹配,或者 mismatches 不包含当前扩展
// 若匹配到了说明当前扩展对象需要进行 wrapper,就创建 wrapper 扩展对象后进行包装
boolean match = (wrapper == null)
|| ((ArrayUtils.isEmpty(wrapper.matches())
|| ArrayUtils.contains(wrapper.matches(), name))
&& !ArrayUtils.contains(wrapper.mismatches(), name));
if (match) {
// 一旦匹配就创建所有 wrapper 类型对象,同时将构造器参数设置为当前类型
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
instance = postProcessAfterInitialization(instance, name);
}
}
}
}
主要是要看在什么情况下才能为当前扩展类型来创建 Wrapper 包装类型:
- Wrapper 注解不存在,前面 6.2.2 是可以通过构造函数来满足 Wrapper 包装条件的
- 存在 Wrapper 注解:matches 属性匹配或者 mismatches 属性不包含当前扩展名称
若匹配到当前扩展对象是需要进行 Wrapper 的,就为当前扩展创建 Wrapper 扩展对象后进行包装
6.3 Wrapper 包装扩展类加载流程图
参考文献
https://www.ktyhub.com/zh/chapter_dubbo/6-extension-wrapper/