/**
* 扩展接口与ExtensionLoader扩展加载器的映射(类共享变量)
* 1)包含了ExtensionFactory接口与其它接口的映射
* 2)每一个SPI接口对应一个ExtensionLoader
* 3)static 静态成员变量,对象之间共享(具体的对象时,EXTENSION_LOADERS、EXTENSION_INSTANCES等static变量是没有存值的)
*
*/
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
/**
* 扩展接口与扩展实例的映射(类共享变量)
*/
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
private final Class<?> type; //扩展接口的类型
private final ExtensionFactory objectFactory; //扩展实例的创建工厂(ExtensionFactory也是SPI接口,1)此处的实例为AdaptiveExtensionFactory@xxx,会用存储的多个扩展工厂查找扩展实例,2)当type=ExtensionFactory.class时,objectFactory=null)
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>(); //扩展实例类Class与扩展名的映射(该缓存中:多个扩展类可以对应同一个扩展名)
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>(); //当前扩展接口中的扩展名与扩展类Class的映射(该缓存中,一个扩展名对应一个扩展类,根据加载策略中的overridden值判断是做覆盖还是抛出异常)
private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>(); //扩展名与@Active注解对象的映射
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>(); //扩展名与扩展实例的映射
private final Holder<Object> cachedAdaptiveInstance = new Holder<>(); //自适应扩展类的实例
private volatile Class<?> cachedAdaptiveClass = null; //自适应扩展类(一个扩展接口最多只有一个自适应扩展类)
private String cachedDefaultName; //缓存默认的扩展名,即为SPI上声明的扩展名
private volatile Throwable createAdaptiveInstanceError; //创建自适应扩展实例时发生的错误
private Set<Class<?>> cachedWrapperClasses; //扩展接口对应的封装类集合(封装类不是扩展类,所以没有在cachedClasses缓存中)
private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>(); //加载时扩展类时的异常信息
private static volatile LoadingStrategy[] strategies = loadLoadingStrategies(); //加载的策略
private ExtensionLoader(Class<?> type) { //私有的构造方法,创建ExtensionLoader实例(指定扩展接口的类型和扩展工厂)
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { //获取扩展接口对应的扩展加载器ExtensionLoader(从缓存中获取,若不存在则重新创建)
if (type == null) { //扩展类型:不为空且是SPI接口
throw new IllegalArgumentException("Extension type == null");
}
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) { //每个SPI接口,对应一个扩展加载器ExtensionLoader,若存在直接返回,否则创建ExtensionLoader
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); //直接从Map中获取值,少了中间变量,更简洁些
}
return loader;
}
public T getExtension(String name, boolean wrap) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
if ("true".equals(name)) { //扩展名为"true",返回默认扩展实例
return getDefaultExtension();
}
final Holder<Object> holder = getOrCreateHolder(name); //获取扩展名对应实例持有类
Object instance = holder.get();
if (instance == null) { //使用双重判断+synchronized来确保单实例
synchronized (holder) {
instance = holder.get();
if (instance == null) { //若缓存中没有扩展实例,则创建对应实例对象
instance = createExtension(name, wrap);
holder.set(instance);
}
}
}
return (T) instance;
}
private T createExtension(String name, boolean wrap) { //创建普通的扩展实例
// 先加载扩展接口对应的所有扩展类Class,然后在找出扩展名对应扩展类Class
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) { //配置文件中,若没有查找到扩展名对应的Class类,则抛出扩展发现异常
throw findException(name);
}
try {
//通过Class的newInstance()创建实例(反射机制)
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); //创建扩展实例,并放入缓存中
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
//注入依赖的扩展实例(类似IOC功能)
injectExtension(instance);
if (wrap) { //使用封装类对扩展实例进行封装(类似AOP功能)
List<Class<?>> wrapperClassesList = new ArrayList<>();
if (cachedWrapperClasses != null) { //当前扩展接口对应的封装类列表,如WrappedExt的封装类列表为Ext5Wrapper1、Ext5Wrapper2
wrapperClassesList.addAll(cachedWrapperClasses);
wrapperClassesList.sort(WrapperComparator.COMPARATOR); //将封装类列表进行排序
Collections.reverse(wrapperClassesList); //将已经排好序的封装类列表进行翻转
}
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
for (Class<?> wrapperClass : wrapperClassesList) {
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
/**
* 判断是否使用封装类封装扩展实例
* a)封装类没有带 @Wrapper注解
* b)封装类带有 @Wrapper注解,且扩展名包含在匹配列表matches中,不在不匹配列表mismatches中
*/
if (wrapper == null
|| (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); //用封装类封装扩展类的实例
}
}
}
}
initExtension(instance); //若实例为Lifecycle类型,则调用Lifecycle#initialize进行初始化
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 {
for (Method method : instance.getClass().getMethods()) {
if (!isSetter(method)) { //只处理set方法
continue;
}
if (method.getAnnotation(DisableInject.class) != null) { //若方法上声明@DisableInject,则不进行注入处理
continue;
}
Class<?> pt = method.getParameterTypes()[0]; //取出set方法中的参数Class
if (ReflectUtils.isPrimitives(pt)) {
continue;
}
try {
String property = getSetterProperty(method); //获取属性名(通过解析方法名称)
Object object = objectFactory.getExtension(pt, property);//此处的objectFactory类型为自适应扩展工厂AdaptiveExtensionFactory,通过遍历其中维护的扩展工厂来获取扩展对象
if (object != null) { //获取到的扩展实例不为空时,则为对象属性设置值,如Ext6扩展接口的实现类Ext6Impl1
method.invoke(instance, object); //使用反射机制调用Set方法,进入扩展对象的依赖注入
}
} 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; //返回处理后的扩展实例
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
try { //资源放在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) {//@csy-010 解析的时候,怎么去掉扫描行里面的空格?如SimpleExt对应的配置文件,解:调用trim()方法
try {
String name = null;
int i = line.indexOf('='); //按等号进行分隔
if (i > 0) { //配置的格式为 extName = className,也可以为 className(不带扩展名)
name = line.substring(0, i).trim(); //扩展名(去前后空格)
line = line.substring(i + 1).trim(); //扩展类对应的全路径类名(去前后空格)
}
if (line.length() > 0 && !isExcluded(line, excludedPackages)) { //扩展类的全路径名称,如org.apache.dubbo.rpc.protocol.dubbo.filter.TraceFilter
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden); //根据扩展类名产生Class,并加载到缓存中
}
} 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,
boolean overridden) throws NoSuchMethodException {
if (!type.isAssignableFrom(clazz)) { //判断实例类是不是接口type的子类型
throw new IllegalStateException("Error occurred when loading extension class (interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + " is not subtype of interface.");
}
if (clazz.isAnnotationPresent(Adaptive.class)) { //缓存自适应扩展类(类上带有@Adaptive注解的扩展类)
cacheAdaptiveClass(clazz, overridden);
} else if (isWrapperClass(clazz)) { //缓存封装类型扩展类(即存在包含以扩展接口为参数的构造方法)
cacheWrapperClass(clazz);
} else { //缓存自动激活扩展类或普通扩展类
clazz.getConstructor();
if (StringUtils.isEmpty(name)) { //什么场景下扩展名为空?解:SPI配置文件中,扩展名为空的情况
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); //多个扩展名可以对应一个扩展类,如xxx.Ext10MultiNames配置的内容,如impl,implMultiName=xxx.Ext10MultiNamesImpl
if (ArrayUtils.isNotEmpty(names)) {
cacheActivateClass(clazz, names[0]); //缓存扩展名与@Activate对象的映射。有多个扩展名时,取第一个扩展名作为自动激活缓存的key
for (String n : names) {
cacheName(clazz, n); //缓存扩展类Class与扩展名的映射(允许多个扩展类Class对应同一个扩展名)
saveInExtensionClass(extensionClasses, clazz, n, overridden); //缓存扩展名与扩展类Class的映射
}
}
}
}
public List<T> getActivateExtension(URL url, String[] values, String group) { //获取自动激活的扩展列表(将URL中配置的参数与@Activate配置的内容进行比较)
List<T> activateExtensions = new ArrayList<>();
List<String> names = values == null ? new ArrayList<>(0) : asList(values); // 扩展名列表(values是从url中获取的指定key对应的参数值,并按分隔符分隔的值列表)
/**
* 类型一:系统激活的扩展类
*/
if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { // 系统激活的扩展类处理,即扩展名列表不包含"-default"
getExtensionClasses(); //加载扩展类。此处没有用到方法的返回值,主要使用方法中的loadExtensionClasses(),值存入成员变量中了,若缓存中没有对应的值,则对应加载并设置到缓存中
for (Map.Entry<String, Object> entry : cachedActivates.entrySet()) { // 遍历从SPI配置文件中加载的@Activate标识的扩展类列表(需要扩展接口有包含@Active注解的实现类)
String name = entry.getKey(); //扩展名
Object activate = entry.getValue(); // @Active对象
String[] activateGroup, activateValue;
if (activate instanceof Activate) { //取注解@Activate上设置的group、value值
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、再比较value)
* 1)判断传入的group是否在注解中group的列表值中
* 2)扩展名name不在自定义的列表中(当前处理的扩展类是系统激活的扩展类)
* 3)将注解中声明的value值与url中参数值进行比较
* 若都满足条件,则获取扩展名对应的实例,并加载到自动激活扩展的列表中
*/
if (isMatchGroup(group, activateGroup)
&& !names.contains(name) //为啥要有这个判断?解答:当前处理的是系统激活的扩展类,而names是自定义的扩展名列表,两者分开处理,所以要进行排除
&& !names.contains(REMOVE_VALUE_PREFIX + name) //对应场景:在设置扩展条件时,把系统激活的类去除,如"-order",即不加到扩展类列表中
&& isActive(activateValue, url)) {
activateExtensions.add(getExtension(name)); // 若匹配,则获取扩展名name对应的实例并加载到列表中
}
}
activateExtensions.sort(ActivateComparator.COMPARATOR); //将可激活扩展类列表进行排序
}
List<T> loadedExtensions = new ArrayList<>();
/**
* 类型二:自定义激活的扩展类
*/
for (int i = 0; i < names.size(); i++) {
String name = names.get(i);
// 带有排除符号"-"的Filter不加载
if (!name.startsWith(REMOVE_VALUE_PREFIX)
&& !names.contains(REMOVE_VALUE_PREFIX + name)) { //@csy-007 此处逻辑会在什么场景下进入?解:处理不再cachedActivates缓存中的扩展,如ExtensionLoaderTest.testLoadDefaultActivateExtension
if (DEFAULT_KEY.equals(name)) { //若指定了"default",则调整对应的顺序
if (!loadedExtensions.isEmpty()) {
activateExtensions.addAll(0, loadedExtensions); //@csy-0014 在指定位置加载列表,原来的值会被覆盖吗?不会覆盖,元素会向后移动
loadedExtensions.clear();
}
} else {
loadedExtensions.add(getExtension(name)); //从cachedClasses缓存中获取指定扩展名对应的扩展类,此处若没有查到指定的扩展,是会抛出没找到扩展的异常
}
}
}
if (!loadedExtensions.isEmpty()) {
activateExtensions.addAll(loadedExtensions);
}
return activateExtensions;
}
public void addExtension(String name, Class<?> clazz) { //添加扩展接口(通过API方式添加,非配置文件中配置)
getExtensionClasses(); // load classes(加载扩展类)
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Input type " +
clazz + " doesn't implement the Extension " + type);
}
if (clazz.isInterface()) {
throw new IllegalStateException("Input type " +
clazz + " can't be interface!");
}
if (!clazz.isAnnotationPresent(Adaptive.class)) { //非自适应扩展类时
if (StringUtils.isBlank(name)) {
throw new IllegalStateException("Extension name is blank (Extension " + type + ")!");
}
if (cachedClasses.get().containsKey(name)) {
throw new IllegalStateException("Extension name " +
name + " already exists (Extension " + type + ")!");
}
cachedNames.put(clazz, name); //符合条件后,设置到缓存中
cachedClasses.get().put(name, clazz);
} else { //自适应扩展类,即类上带有@Adaptive注解(一个扩展接口,最多只有一个自适应扩展类)
if (cachedAdaptiveClass != null) { //添加扩展时,自适应类已存在,则抛出异常
throw new IllegalStateException("Adaptive Extension already exists (Extension " + type + ")!");
}
cachedAdaptiveClass = clazz; //自适应扩展,是不需要处理扩展名的
}
}
private static final Logger logger = LoggerFactory.getLogger(AdaptiveClassCodeGenerator.class);
private static final String CLASSNAME_INVOCATION = "org.apache.dubbo.rpc.Invocation";
private static final String CODE_PACKAGE = "package %s;\n"; //包信息对应的字符串,使用字符串的占位符,来替换具体的值
private static final String CODE_IMPORTS = "import %s;\n"; //导入信息对应的字符串
private static final String CODE_CLASS_DECLARATION = "public class %s$Adaptive implements %s {\n"; //类的声明信息对应的字符串
private static final String CODE_METHOD_DECLARATION = "public %s %s(%s) %s {\n%s}\n"; //方法的声明信息对应的字符串
private static final String CODE_METHOD_ARGUMENT = "%s arg%d"; //方法参数对应的字符串
private static final String CODE_EXTENSION_METHOD_INVOKE_ARGUMENT = "arg%d"; //拼接的内容,用占位符进行处理
private final Class<?> type; //SPI扩展接口
public String generate() {
// no need to generate adaptive class since there's no adaptive method found.
if (!hasAdaptiveMethod()) { //判断是否有自适应方法,如无则抛出异常
throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
}
// 构建自适应实现类:包含package语句、import语句、Class声明、SPI接口中各个方法的对应实现
StringBuilder code = new StringBuilder();
code.append(generatePackageInfo()); //把功能点用对应的方法表示,清晰明了,并且使单个方法的内容变少
code.append(generateImports());
code.append(generateClassDeclaration());
Method[] methods = type.getMethods();
for (Method method : methods) { //遍历SPI接口的方法,并对应产生方法对应的代码
code.append(generateMethod(method));
}
code.append("}");
if (logger.isDebugEnabled()) {
logger.debug(code.toString());
}
return code.toString();
}
private String generateMethod(Method method) {
//构建方法:包含方法返回类型、方法名、方法参数、抛出的异常、内容
String methodReturnType = method.getReturnType().getCanonicalName(); //获取规范的返回类型,如java.lang.String
String methodName = method.getName();
String methodContent = generateMethodContent(method); // 产生方法内容
String methodArgs = generateMethodArguments(method); //如:org.apache.dubbo.common.URL arg0, java.lang.String arg1
String methodThrows = generateMethodThrows(method);
// CODE_METHOD_DECLARATION = "public %s %s(%s) %s {\n%s}\n";
return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);
}
private String generateMethodContent(Method method) {
Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
StringBuilder code = new StringBuilder(512);
if (adaptiveAnnotation == null) {
return generateUnsupported(method); //方法未带@Adaptive注解时,产生不支持操作的描述
} else {
int urlTypeIndex = getUrlTypeIndex(method);
// found parameter in URL type
if (urlTypeIndex != -1) {
// Null Point check
code.append(generateUrlNullCheck(urlTypeIndex)); //产生URL非空检查的语句
} else {
// did not find parameter in URL type
//@csy-011 未找到url参数时的处理逻辑是怎样的?遍历参数Class列表,然后依次查看参数Class对应的方法,判断是否有返回值为URL的get方法,若有则进行相关处理
code.append(generateUrlAssignmentIndirectly(method)); //间接地通过方法中的参数获取URL,并产生URL非空检查的语句
}
String[] value = getMethodAdaptiveValue(adaptiveAnnotation); //获取方法上@Adaptive声明的值
boolean hasInvocation = hasInvocationArgument(method); //判断方法参数列表中是否存在Invocation类型参数
code.append(generateInvocationArgumentNullCheck(method)); //产生Invocation类型参数的非空检查的语句
code.append(generateExtNameAssignment(value, hasInvocation)); //产生获取扩展名的语句(**重点逻辑**)
// check extName == null?
code.append(generateExtNameNullCheck(value)); //产生扩展名非空检查的语句
code.append(generateExtensionAssignment()); //产生获取扩展实例的语句
// return statement
code.append(generateReturnAndInvocation(method)); //产生方法调用以及有返回值时返回Return语句
}
return code.toString();
}
不管是自适应扩展类@Adaptive、还是自动激活扩展类@Activate,最终都是找到明确的扩展名,然后通过getExtension(name)找到扩展实例
不过查找扩展名方式有些不同,
a)@Adaptive(value={“key1”,“key2”}),最终是通过 url.getParameter(“key1”,getParameter(“key2”,defaultExtName)) 从url中查找到指定参数对应的扩展名,
b)@Activate有两种形式,一种是自定义激活,另一种是系统自动激活
b.1)自定义激活:ExtensionLoader#getActivateExtension(URL url, String key),直接将url中key对应的值作为扩展名,不需要带上@Activate注解
b.2)自动自动激活:对@Activate注解中的group、value进行比较,满足条件了,就使用@Activate注解对应的扩展名,有两种形式
b.2.1)如@Activate(value={key1,key2}, group=“default_group”),则满足group匹配且,key1、key2出现在url参数的key中。
b.2.2)如@Activate(value={key1:value1,key2:value2}, group=“default_group”),则满足group匹配且,key1、value1或key2、value2任意一个键值对同时出现在url参数中,
即该@Activate注解对应的实例被匹配,然后再到缓存中找到注解对应的扩展名
获取实例时,getExtension、getAdaptiveExtension、getActivateExtensionsion获取实例时,都会先调用getExtensionClasses()把扩展类加到缓存中(若已经加载过,则从缓存中取)。getExtensionClasses()中的loadClass()能够分类存储。
@Activate自动激活扩展类进行匹配时,group和value条件只要没配置,就表明不使用group、value做限制,即匹配所有。如group没有配置,那么所有group扩展类都能匹配;没有配置value,那么所有value的扩展类都能匹配。
创建扩展类实例时,默认是会自动注入依赖的,若不想自动注册依赖,在setXxx方法上加上@DisableInject注解。
一个扩展名只能对应一个扩展类,一个扩展类可以对应多个扩展名,即扩展类与扩展名时是一对多的关系,在配置文件中,扩展名可以配置多个,用逗号分隔。