ExtensionLoader是dubbo实现SPI的核心类。ExtentionLoader的逻辑入口可以分为getExtension、getAdaptiveExtension、getActivateExtension三个。分别是普通扩展类、自适应扩展类、和激活扩展类。
1. getExtension实现原理
方法逻辑:先通过参数name判断是否为true,不为true再通过#createExtension方法获取扩展点实例然后把它放入缓存。
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
//name=true
if ("true".equals(name)) {
return getDefaultExtension(); //默认扩展点
}
Holder<Object> holder = getOrCreateHolder(name);
Object instance = holder.get();
if (instance == null) {
synchronized (holder) {
instance = holder.get();
if (instance == null) {
//获取Protocol对应的实例
instance = createExtension(name);
//把Protocol的实例放到缓存里面
holder.set(instance);
}
}
}
return (T) instance;
}
createExtension方法:先获取扩展点对应的实现类,调用#getExtensionClasses方法。这个方法,会查找指定目录 /META-INF/dubbo || /META-INF/services 下对应的 type->也就是本次演示案例的 Protocol 的 properties 文件,然后扫描这个文 件下的所有配置信息。然后保存到一个 HashMap 中(classes),key=name(对应 protocol 文件中配置的 protocol), value=对 应配置的类的实例。然后从缓存中获取扩展实例,如果为null则放入缓存中。接着进行依赖属性注入,获取包装扩展对象。
//创建扩展名对应的扩展实例
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);
// 创建 Wrapper 拓展对象
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
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 + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
//获取扩展点对应的实现类,先从缓存中获取,没有则从配置文件中加载
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;
}
#injectExtension注入依赖属性:遍历类中的方法,方法以set开头,含有一个参数并且满足public修饰。符合条件的通过参数类型从ExtensionFactory获取实例,然后把实例注入进去。
private T injectExtension(T instance) {
try {
if (objectFactory != null) {
for (Method method : instance.getClass().getMethods()) {
//判断方法是否以set开头,只有一个参数并且用public修饰
if (isSetter(method)) {
/**
* 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 {
String property = getSetterProperty(method);
//从ExtensionFactory中获取实例
Object object = objectFactory.getExtension(pt, property);
if (object != null) {
//调用 set 方法进行赋值
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;
}
2. getAdaptiveExtension实现原理
在#getAdaptiveExtension方法中,会给扩展点接口自动生成实现类的字符串,然后通过编译器将实现类字符串编译为自适应类并返回。在实现类上可以看到有@Adaptive注解。实现类字符串生成主要逻辑总结如下:
(1) 生成package、import、类名称等头部信息。此处只会引入一个ExtensionClassLoader,为了不写import其他类,其他方法调用时全部使用全路径。类名为:接口名$Adaptive。
(2) 遍历接口所有方法,获取方法的返回类型、参数类型、异常类型等。为(3)判断是否为空做准备。
(3) 生成参数为空校验代码,如果有远程调用还会加上Invocation参数为空的校验。
(4) 生成默认实现类名称。
(5) 生成获取扩展点名称的代码。根据@Adaptive注解中配置的key值生成不同的获取代码。
(6) 生成获取具体扩展实现类代码,最终还是通过getExtension(extName)方法获取自适应扩展类的真正实现。
//获取自适应扩展点
public T getAdaptiveExtension() {
// 从缓存中,获得自适应拓展对象
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("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
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);
}
}
3. getActivateExtension实现原理
public List<T> getActivateExtension(URL url, String key, String group) {
String value = url.getParameter(key);
return getActivateExtension(url, StringUtils.isEmpty(value) ? null : COMMA_SPLIT_PATTERN.split(value), group);
}
public List<T> getActivateExtension(URL url, String[] values, String group) {
List<T> exts = new ArrayList<>();
List<String> names = values == null ? new ArrayList<>(0) : Arrays.asList(values);
if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) {
// 获得拓展实现类数组
getExtensionClasses();
for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) {
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;
}
if (isMatchGroup(group, activateGroup)) {
// 获得拓展对象
T ext = getExtension(name);
if (!names.contains(name) // 不包含在自定义配置里。如果包含,会在下面的代码处理。
&& !names.contains(REMOVE_VALUE_PREFIX + name)// 判断是否配置移除。例如 <dubbo:service filter="-monitor" />,则 MonitorFilter 会被移除
&& isActive(activateValue, url)) {// 判断是否激活
exts.add(ext);
}
}
}
exts.sort(ActivateComparator.COMPARATOR);
}
List<T> usrs = 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 (!usrs.isEmpty()) {
exts.addAll(0, usrs);
usrs.clear();
}
} else {
T ext = getExtension(name);
usrs.add(ext);
}
}
}
if (!usrs.isEmpty()) {
exts.addAll(usrs);
}
return exts;
}