@SPI("impl1")publicinterfaceSimpleExt{// @Adaptive example, do not specify a explicit key.@Adaptive
String echo(URL url, String s);@Adaptive({"key1","key2"})
String yell(URL url, String s);// no @Adaptive
String bang(URL url,int i);}
/**
* EXTENSION_LOADERS 缓存中查找相应的 ExtensionLoader 实例
*
* @param type
* @param <T>
* @return
*/@SuppressWarnings("unchecked")publicstatic<T> ExtensionLoader<T>getExtensionLoader(Class<T> type){//如果类型为空那么就直接报错if(type == null){thrownewIllegalArgumentException("Extension type == null");}//判断类型是否是接口if(!type.isInterface()){thrownewIllegalArgumentException("Extension type ("+ type +") is not an interface!");}//判断这个类上是否有SPI接口if(!withExtensionAnnotation(type)){thrownewIllegalArgumentException("Extension type ("+ type +") is not an extension, because it is NOT annotated with @"+ SPI.class.getSimpleName()+"!");}/**
* 从缓存中获取 根据类型获取加载器 org.apache.dubbo.common.extension.ExtensionFactory
*/
ExtensionLoader<T> loader =(ExtensionLoader<T>) EXTENSION_LOADERS.get(type);/**
* 取不到创建一个放入EXTENSION_LOADERS中
*/if(loader == null){//如果存在key,就不保存(原来是key直接被替换)//new ExtensionLoader()去执行默认的构造方法
EXTENSION_LOADERS.putIfAbsent(type,newExtensionLoader<T>(type));
loader =(ExtensionLoader<T>) EXTENSION_LOADERS.get(type);}return loader;}
privatevoidloadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
java.net.URL resourceURL,boolean overridden, String... excludedPackages){try{try(BufferedReader reader =newBufferedReader(newInputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))){
String line;while((line = reader.readLine())!= null){/**
* # 之前的内容是我们需要的数据,后面的内容可以认为是注释之类的
*/finalint 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('=');if(i >0){
name = line.substring(0, i).trim();
line = line.substring(i +1).trim();}if(line.length()>0&&!isExcluded(line, excludedPackages)){/**
* 加载解析出来的类的全限定名称
*/
Class<?> clazz = Class.forName(line,true, classLoader);//加载资源loadClass(extensionClasses, resourceURL, clazz, name, overridden);}}catch(Throwable t){
IllegalStateException e =newIllegalStateException("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);}}
privatevoidloadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name,boolean overridden)throws NoSuchMethodException {/**
* 判断是新加载clazz是否是type的子类,不是报错
*/if(!type.isAssignableFrom(clazz)){thrownewIllegalStateException("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)){/**
* 将此类作为cachedAdaptiveClass
*/cacheAdaptiveClass(clazz, overridden);/**
* 如果这个类,没有Adaptive注解
*/}elseif(isWrapperClass(clazz)){cacheWrapperClass(clazz);// 处理Wrapper类}else{
clazz.getConstructor();// 扩展实现类必须有无参构造函数if(StringUtils.isEmpty(name)){
name =findAnnotationName(clazz);if(name.length()==0){thrownewIllegalStateException("No such extension name for the class "+ clazz.getName()+" in the config "+ resourceURL);}}// 兜底:SPI配置文件中未指定扩展名称,则用类的简单名称作为扩展名(略)
String[] names = NAME_SEPARATOR.split(name);if(ArrayUtils.isNotEmpty(names)){// 将包含@Activate注解的实现类缓存到cachedActivates集合中cacheActivateClass(clazz, names[0]);for(String n : names){// 在cachedNames集合中缓存实现类->扩展名的映射cacheName(clazz, n);// 在cachedClasses集合中缓存扩展名->实现类的映射saveInExtensionClass(extensionClasses, clazz, n, overridden);}}}}