Dubbo实例注入过程
作者:hello_zzw
文章主要介绍了Dubbo框架中ExtensionLoader类的创建、初始化、后处理和注入扩展点的详细过程,特别是通过AdaptiveExtensionInjector进行注入的部分
Dubbo实例注入
org.apache.dubbo.common.extension.ExtensionLoader#createExtension
/**
* 根据指定扩展点名称去创建扩展点实例对象
*/
@SuppressWarnings("unchecked")
private T createExtension(String name, boolean wrap) {
// getExtensionClasses 为当前 SPI 接口的所有实现类的类信息集合
// 通过指定的扩展点名称 name 来获取与之对应的实现类类信息
Class<?> clazz = getExtensionClasses().get(name);
// 若找不到对应的扩展点,或者当初加载时扩展点有重复名称抛出异常
if (clazz == null || unacceptableExceptions.contains(name)) {
throw findException(name);
}
try {
// extensionInstances 为当前 SPI 接口已经经过实例化的实例对象集合
// 然后通过指定的扩展点名称看看有没有与之对应的已经曾经创建好的实例对象
T instance = (T) extensionInstances.get(clazz);
// 若找不到,说明没有缓存,从而则说明该扩展点名称也是首次使用
if (instance == null) {
// 通过并发 Map 的 putIfAbsent 方法以线程安全的形式,
// 来保证该实现类只会创建一个实例对象,实例对象是反射方式创建出来的
extensionInstances.putIfAbsent(clazz, createExtensionInstance(clazz));
// 获取刚刚创建的实例对象
instance = (T) extensionInstances.get(clazz);
// 初始化前置处理,即将原始的对象进行前置包装等处理
instance = postProcessBeforeInitialization(instance, name);
// 扩展点注入
injectExtension(instance);
// 初始化后置处理,即将已初始化实例化注入的对象进行后置包装等处理
instance = postProcessAfterInitialization(instance, name);
}
// wrap 是否需要进行装饰器包装
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
// 看看是否有装饰器包装类,即实现类中单一参数的构造方法是不是 SPI 接口
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
wrapperClassesList.sort(WrapperComparator.COMPARATOR);
Collections.reverse(wrapperClassesList);
}
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
// 循环装饰器包装类,进行层层套娃包装
for (Class<?> wrapperClass : wrapperClassesList) {
// 装饰器类上是否 Wrapper 注解
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
// 1. 没有 wrapper 注解,需要进行包装
// 2. wrapper 中的 matches 字段值为空没有内容,需要进行包装
// 3. wrapper 中的 matches 字段值不为空并包含入参 name 值,并且 mismatches 字段值不包含 name 值,需要进行包装
// 4. 其他情况,可能就是瞎写乱配,导致无法进行包装之类的
boolean match = (wrapper == null)
|| ((ArrayUtils.isEmpty(wrapper.matches())
|| ArrayUtils.contains(wrapper.matches(), name))
&& !ArrayUtils.contains(wrapper.mismatches(), name));
// 如果匹配成功,则进行包装
if (match) {
// 针对包装的类再次进行实例注入
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.
initExtension(instance);
return instance;
} catch (Throwable t) {
throw new IllegalStateException(
"Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: "
+ t.getMessage(),
t);
}
}
org.apache.dubbo.common.extension.ExtensionLoader#postProcessBeforeInitialization
/**
* 初始化前置处理方法
*/
@SuppressWarnings("unchecked")
private T postProcessBeforeInitialization(T instance, String name) throws Exception {
// 存在扩展后处理器时,循环处理所有的后置处理器
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
// 循环调用所有后置处理器中的初始化前置方法
instance = (T) processor.postProcessBeforeInitialization(instance, name);
}
}
// 返回处理后的对象
return instance;
}
/**
* 初始化后置处理方法
*/
@SuppressWarnings("unchecked")
private T postProcessAfterInitialization(T instance, String name) throws Exception {
// 如果实例实现了ExtensionAccessorAware,自动注入extensionDirector作为扩展访问器
if (instance instanceof ExtensionAccessorAware) {
((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector);
}
// 存在扩展后处理器时,循环处理所有的后置处理器
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
// 循环调用所有后置处理器中的初始化后置方法
instance = (T) processor.postProcessAfterInitialization(instance, name);
}
}
return instance;
}
org.apache.dubbo.common.extension.ExtensionLoader#injectExtension
/**
* 注入扩展点的方法
*/
private T injectExtension(T instance) {
if (injector == null) {
return instance;
}
try {
// 循环处理实例对象的所有public方法
for (Method method : instance.getClass().getMethods()) {
// 只处理set开头,public修饰,只有一个参数的方法
if (!isSetter(method)) {
continue;
}
// 不处理带有DisableInject注解的方法
if (method.isAnnotationPresent(DisableInject.class)) {
continue;
}
// 过滤掉实现自ScopeModelAware的方法
if (method.getDeclaringClass() == ScopeModelAware.class) {
continue;
}
// 过滤掉 ScopeModelAware、ExtensionAccessorAware 的方法
if (instance instanceof ScopeModelAware || instance instanceof ExtensionAccessorAware) {
if (ignoredInjectMethodsDesc.contains(ReflectUtils.getDesc(method))) {
continue;
}
}
// 获取第一个参数
Class<?> pt = method.getParameterTypes()[0];
// 基础类型不做处理
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
// 获取set方法对应的属性
// set方法大于三个分字符时,去除set后抽字母小写
// 小于等于三个字符时,返回""
String property = getSetterProperty(method);
// 根据参数类型、属性名称 从容器中获取对应的实例对象
Object object = injector.getInstance(pt, property);
if (object != null) {
// 获取到实例对象时,使用set方法设置到对象中
method.invoke(instance, object);
}
} catch (Exception e) {
logger.error(
COMMON_ERROR_LOAD_EXTENSION,
"",
"",
"Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": "
+ e.getMessage(),
e);
}
}
} catch (Exception e) {
logger.error(COMMON_ERROR_LOAD_EXTENSION, "", "", e.getMessage(), e);
}
return instance;
}
org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector
@Override
public void initialize() throws IllegalStateException {
// 获取【扩展点注入器】的加载器
ExtensionLoader<ExtensionInjector> loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
injectors = loader.getSupportedExtensions().stream()
// 从加载器中拿出所有的可被使用的注册器实现类
.map(loader::getExtension)
// 包装在不可变集合中
.collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList));
}
@Override
public <T> T getInstance(final Class<T> type, final String name) {
// 循环所有的扩展点注入器
return injectors.stream()
// 从容器中根据类型加名字获取实例对象
.map(injector -> injector.getInstance(type, name))
.filter(Objects::nonNull)
// 获取到第一个就结束
.findFirst()
.orElse(null);
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
