1 package com.alibaba.dubbo.demo.test; 2 3 import com.alibaba.dubbo.common.extension.ExtensionLoader; 4 import com.alibaba.dubbo.rpc.Protocol; 5 6 public class TestExtension { 7 public static void main(String[] args) { 8 ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class); 9 final Protocol dubboProtocol = loader.getExtension("dubbo"); 10 final Protocol adaptiveExtension = loader.getAdaptiveExtension(); 11 } 12 }
講解這三行代碼的源碼。java
一 Protocol接口的定義spring
1 package com.alibaba.dubbo.rpc; 2 3 import com.alibaba.dubbo.common.URL; 4 import com.alibaba.dubbo.common.extension.Adaptive; 5 import com.alibaba.dubbo.common.extension.SPI; 6 7 /** 8 * Protocol. (API/SPI, Singleton, ThreadSafe) 9 */ 10 @SPI("dubbo") 11 public interface Protocol { 12 13 /** 14 * 獲取缺省端口,當用戶沒有配置端口時使用。 15 * 16 * @return 缺省端口 17 */ 18 int getDefaultPort(); 19 20 /** 21 * 暴露遠程服務:<br> 22 * 1. 協議在接收請求時,應記錄請求來源方地址信息:RpcContext.getContext().setRemoteAddress();<br> 23 * 2. export()必須是冪等的,也就是暴露同一個URL的Invoker兩次,和暴露一次沒有區別。<br> 24 * 3. export()傳入的Invoker由框架實現並傳入,協議不須要關心。<br> 25 * 26 * @param <T> 服務的類型 27 * @param invoker 服務的執行體 28 * @return exporter 暴露服務的引用,用於取消暴露 29 * @throws RpcException 當暴露服務出錯時拋出,好比端口已佔用 30 */ 31 @Adaptive 32 <T> Exporter<T> export(Invoker<T> invoker) throws RpcException; 33 34 /** 35 * 引用遠程服務:<br> 36 * 1. 當用戶調用refer()所返回的Invoker對象的invoke()方法時,協議需相應執行同URL遠端export()傳入的Invoker對象的invoke()方法。<br> 37 * 2. refer()返回的Invoker由協議實現,協議一般須要在此Invoker中發送遠程請求。<br> 38 * 3. 當url中有設置check=false時,鏈接失敗不能拋出異常,並內部自動恢復。<br> 39 * 40 * @param <T> 服務的類型 41 * @param type 服務的類型 42 * @param url 遠程服務的URL地址 43 * @return invoker 服務的本地代理 44 * @throws RpcException 當鏈接服務提供方失敗時拋出 45 */ 46 @Adaptive 47 <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException; 48 49 /** 50 * 釋放協議:<br> 51 * 1. 取消該協議全部已經暴露和引用的服務。<br> 52 * 2. 釋放協議所佔用的全部資源,好比鏈接和端口。<br> 53 * 3. 協議在釋放後,依然能暴露和引用新的服務。<br> 54 */ 55 void destroy(); 56 }
注意:這裏有兩個核心註解設計模式
1 @Documented 2 @Retention(RetentionPolicy.RUNTIME) 3 @Target({ElementType.TYPE}) 4 public @interface SPI { 5 /** 缺省擴展點名 */ 6 String value() default ""; 7 }
@Adaptive:該註解能夠註解在兩個地方:緩存
這個接口極其重要,後續的整個服務暴露和服務調用會用到該接口的兩個方法。app
二 獲取ExtensionLoader框架
1 ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
ExtensionLoader能夠類比爲JDK-SPI中的ServiceLoader。this
首先來看一下ExtensionLoader的類屬性:url
1 /** 存放SPI文件的三個目錄,其中META-INF/services/也是jdk的SPI文件的存放目錄 */ 2 private static final String SERVICES_DIRECTORY = "META-INF/services/"; 3 private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; 4 private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";//這個是最終jar包中存放spi文件的位置 5 6 private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); 7 /** key: SPI接口Class value: 該接口的ExtensionLoader */ 8 private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>(); 9 /** key: SPI接口Class value: SPI實現類的對象實例 */ 10 private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
注意:上述的都是類屬性,即全部該類的實例都共享。然後邊的實例屬性就屬於每個類的實例私有。spa
再來看一下ExtensionLoader的實例屬性:.net
1 /** SPI接口Class */ 2 private final Class<?> type; 3 /** SPI實現類對象實例的建立工廠 */ 4 private final ExtensionFactory objectFactory; 5 /** key: ExtensionClass的Class value: SPI實現類的key */ 6 private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>(); 7 /** 存放全部的extensionClass */ 8 private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>(); 9 10 private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>(); 11 /** 緩存建立好的extensionClass實例 */ 12 private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>(); 13 /** 緩存建立好的適配類實例 */ 14 private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>(); 15 /** 存儲類上帶有@Adaptive註解的Class */ 16 private volatile Class<?> cachedAdaptiveClass = null; 17 /** 默認的SPI文件中的key */ 18 private String cachedDefaultName; 19 /** 存儲在建立適配類實例這個過程當中發生的錯誤 */ 20 private volatile Throwable createAdaptiveInstanceError; 21 /** 存放具備一個type入參的構造器的實現類的Class對象 */ 22 private Set<Class<?>> cachedWrapperClasses; 23 /** key :實現類的全類名 value: exception, 防止真正的異常被吞掉 */ 24 private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
來看一下getExtensionLoader(Class<T> type)的源碼:
1 /** 2 * 1 校驗入參type:非空 + 接口 + 含有@SPI註解 3 * 2 根據type接口從全局緩存EXTENSION_LOADERS中獲取ExtensionLoader,若是有直接返回;若是沒有,則先建立,以後放入緩存,最後返回 4 */ 5 public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { 6 if (type == null) 7 throw new IllegalArgumentException("Extension type == null"); 8 if (!type.isInterface()) { 9 throw new IllegalArgumentException("Extension type(" + type + ") is not interface!"); 10 } 11 if (!withExtensionAnnotation(type)) { 12 throw new IllegalArgumentException("Extension type(" + type + 13 ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); 14 } 15 16 ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); 17 if (loader == null) { 18 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); 19 loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); 20 } 21 return loader; 22 }
建立ExtensionLoader:
1 private ExtensionLoader(Class<?> type) { 2 this.type = type; 3 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); 4 }
當前建立的ExtensionLoader對象(咱們取名爲ExtensionLoader對象1)的type是com.alibaba.dubbo.rpc.Protocol,因此此時會執行:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()。
首先是建立ExtensionFactory,經過上邊核心類部分ExtensionFactory接口的源碼能夠看出,此類也是一個SPI接口類,且沒有指定默認的實現類的key。
1 ExtensionLoader.getExtensionLoader(ExtensionFactory.class)
下面的代碼與上述的過程類似,只是此時建立的另一個ExtensionLoader對象(咱們取名爲ExtensionLoader對象2)的type是com.alibaba.dubbo.common.extension.ExtensionFactory,而objectFactory是null。以後,這個ExtensionLoader對象2被放入EXTENSION_LOADERS緩存。這裏給出ExtensionFactory的定義,該類也極其重要。//TODO
1 package com.alibaba.dubbo.common.extension; 2 3 @SPI 4 public interface ExtensionFactory { 5 <T> T getExtension(Class<T> type, String name); 6 }
以後執行ExtensionLoader對象2的getAdaptiveExtension()方法。
1 /** 2 * 首先從cachedAdaptiveInstance緩存中獲取AdaptiveExtension實例 3 * 若是不爲null, 直接返回; 4 * 若是爲null, 先建立AdaptiveExtension實例, 以後放入cachedAdaptiveInstance緩存中,最後返回 5 */ 6 public T getAdaptiveExtension() { 7 Object instance = cachedAdaptiveInstance.get(); 8 if (instance == null) { 9 if (createAdaptiveInstanceError == null) { 10 synchronized (cachedAdaptiveInstance) { 11 instance = cachedAdaptiveInstance.get(); 12 if (instance == null) { 13 try { 14 instance = createAdaptiveExtension(); 15 cachedAdaptiveInstance.set(instance); 16 } catch (Throwable t) { 17 createAdaptiveInstanceError = t; 18 throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t); 19 } 20 } 21 } 22 } else { 23 throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); 24 } 25 } 26 27 return (T) instance; 28 }
來看createAdaptiveExtension()建立AdaptiveExtension的源碼:
1 /** 2 * createAdaptiveExtension() 3 * --getAdaptiveExtensionClass() 4 * //從dubbo-spi配置文件中獲取AdaptiveExtensionClass 5 * --getExtensionClasses() 6 * --loadExtensionClasses() 7 * --loadFile(Map<String, Class<?>> extensionClasses, String dir) 8 * //建立動態代理類 9 * --createAdaptiveExtensionClass() 10 * 11 * --injectExtension(T instance) //dubbo-ioc 12 */ 13 private T createAdaptiveExtension() { 14 try { 15 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); 16 } catch (Exception e) { 17 throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e); 18 } 19 }
調用層級看註釋。injectExtension(T instance)方法只對objectFactory有用,若是objectFactory==null,則直接返回T instance。因此這裏返回的是getAdaptiveExtensionClass().newInstance()
來看getAdaptiveExtensionClass()的源碼:
1 /** 2 * 獲取ExtensionClasses和適配類 3 * 若是實現類上帶有@Adaptive註解,直接建立修飾類 4 * 若是方法上帶有@Adaptive註解,動態生成代理類 5 */ 6 private Class<?> getAdaptiveExtensionClass() { 7 getExtensionClasses(); 8 if (cachedAdaptiveClass != null) { 9 return cachedAdaptiveClass; 10 } 11 return cachedAdaptiveClass = createAdaptiveExtensionClass(); 12 }
如今來看getExtensionClasses():
1 /** 2 * 先從cachedClasses緩存中獲取全部的ExtensionClass,若是有,直接返回; 3 * 若是沒有,經過loadExtensionClasses()從SPI文件中去讀取,以後寫入緩存 4 */ 5 private Map<String, Class<?>> getExtensionClasses() { 6 Map<String, Class<?>> classes = cachedClasses.get(); 7 if (classes == null) { 8 synchronized (cachedClasses) { 9 classes = cachedClasses.get(); 10 if (classes == null) { 11 classes = loadExtensionClasses(); 12 cachedClasses.set(classes); 13 } 14 } 15 } 16 return classes; 17 }
如今來看loadExtensionClasses()
1 /** 2 * 1 從@SPI註解中將默認值解析出來,並緩存到cachedDefaultName中 3 * 2 從SPI文件中獲取extensionClass並存儲到extensionClasses中,最後返回extensionClasses 4 * 注意:此方法已經getExtensionClasses方法同步過。 5 */ 6 private Map<String, Class<?>> loadExtensionClasses() { 7 final SPI defaultAnnotation = type.getAnnotation(SPI.class); 8 if (defaultAnnotation != null) { 9 String value = defaultAnnotation.value(); 10 if (value != null && (value = value.trim()).length() > 0) { 11 String[] names = NAME_SEPARATOR.split(value); 12 if (names.length > 1) { 13 throw new IllegalStateException("more than 1 default extension name on extension " + type.getName() 14 + ": " + Arrays.toString(names)); 15 } 16 if (names.length == 1) cachedDefaultName = names[0]; 17 } 18 } 19 20 Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>(); 21 loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); 22 loadFile(extensionClasses, DUBBO_DIRECTORY); 23 loadFile(extensionClasses, SERVICES_DIRECTORY); 24 return extensionClasses; 25 }
以後來看一下很是重要的一個方法loadFile(Map<String, Class<?>> extensionClasses, String dir)。
1 /** 2 * 1 加載dir目錄下的指定type名稱的文件(例如:dubbo-2.5.5.jar中的/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory) 3 * 2 遍歷該文件中的每一行 4 * (1)獲取實現類key和value, 例如 name=spi, line=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 5 * (2)根據line建立Class對象 6 * (3)將具備@Adaptive註解的實現類的Class對象放在cachedAdaptiveClass緩存中, 注意該緩存只能存放一個具備@Adaptive註解的實現類的Class對象,若是有兩個知足條件,則拋異常 7 * 下面的都是對不含@Adaptive註解的實現類的Class對象: 8 * (4)查看是否具備含有一個type入參的構造器, 若是有(就是wrapper類), 將當前的Class對象放置到cachedWrapperClasses緩存中 9 * (5)若是沒有含有一個type入參的構造器, 獲取無參構造器. 若是Class對象具備@Active註解, 將該對象以<實現類的key, active>存儲起來 10 * (6)最後,將<Class對象, 實現類的key>存入cachedNames緩存,並將這些Class存入extensionClasses中. 11 * @param extensionClasses 12 * @param dir 13 */ 14 private void loadFile(Map<String, Class<?>> extensionClasses, String dir) { 15 String fileName = dir + type.getName(); 16 try { 17 Enumeration<java.net.URL> urls; 18 ClassLoader classLoader = findClassLoader(); 19 if (classLoader != null) { 20 urls = classLoader.getResources(fileName); 21 } else { 22 urls = ClassLoader.getSystemResources(fileName); 23 } 24 if (urls != null) { 25 while (urls.hasMoreElements()) { 26 java.net.URL url = urls.nextElement(); 27 try { 28 BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); 29 try { 30 String line = null; 31 while ((line = reader.readLine()) != null) { 32 final int ci = line.indexOf('#'); 33 if (ci >= 0) line = line.substring(0, ci); 34 line = line.trim(); 35 if (line.length() > 0) { 36 try { 37 String name = null; 38 int i = line.indexOf('='); 39 if (i > 0) { 40 name = line.substring(0, i).trim(); 41 line = line.substring(i + 1).trim(); 42 } 43 if (line.length() > 0) { 44 Class<?> clazz = Class.forName(line, true, classLoader); 45 if (!type.isAssignableFrom(clazz)) { 46 throw new IllegalStateException("Error when load extension class(interface: " + 47 type + ", class line: " + clazz.getName() + "), class " 48 + clazz.getName() + "is not subtype of interface."); 49 } 50 if (clazz.isAnnotationPresent(Adaptive.class)) { 51 if (cachedAdaptiveClass == null) { 52 cachedAdaptiveClass = clazz; 53 } else if (!cachedAdaptiveClass.equals(clazz)) { 54 throw new IllegalStateException("More than 1 adaptive class found: " 55 + cachedAdaptiveClass.getClass().getName() 56 + ", " + clazz.getClass().getName()); 57 } 58 } else { 59 try { 60 clazz.getConstructor(type); 61 Set<Class<?>> wrappers = cachedWrapperClasses; 62 if (wrappers == null) { 63 cachedWrapperClasses = new ConcurrentHashSet<Class<?>>(); 64 wrappers = cachedWrapperClasses; 65 } 66 wrappers.add(clazz); 67 } catch (NoSuchMethodException e) { 68 clazz.getConstructor(); 69 if (name == null || name.length() == 0) { 70 name = findAnnotationName(clazz); 71 if (name == null || name.length() == 0) { 72 if (clazz.getSimpleName().length() > type.getSimpleName().length() 73 && clazz.getSimpleName().endsWith(type.getSimpleName())) { 74 name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase(); 75 } else { 76 throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url); 77 } 78 } 79 } 80 String[] names = NAME_SEPARATOR.split(name); 81 if (names != null && names.length > 0) { 82 Activate activate = clazz.getAnnotation(Activate.class); 83 if (activate != null) { 84 cachedActivates.put(names[0], activate); 85 } 86 for (String n : names) { 87 if (!cachedNames.containsKey(clazz)) { 88 cachedNames.put(clazz, n); 89 } 90 Class<?> c = extensionClasses.get(n); 91 if (c == null) { 92 extensionClasses.put(n, clazz); 93 } else if (c != clazz) { 94 throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName()); 95 } 96 } 97 } 98 } 99 } 100 } 101 } catch (Throwable t) { 102 IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t); 103 exceptions.put(line, e); 104 } 105 } 106 } // end of while read lines 107 } finally { 108 reader.close(); 109 } 110 } catch (Throwable t) { 111 logger.error("Exception when load extension class(interface: " + 112 type + ", class file: " + url + ") in " + url, t); 113 } 114 } // end of while urls 115 } 116 } catch (Throwable t) { 117 logger.error("Exception when load extension class(interface: " + 118 type + ", description file: " + fileName + ").", t); 119 } 120 }
上述的方法分別從三個目錄查找SPI文件並進行加載。在這裏只有在META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory中有值,內容以下:
1 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
2 spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 3 spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
其中AdaptiveExtensionFactory在類上具備@Adaptive註解,這個類會在後續去講,這裏先略過。
執行事後,看一下:
上邊一直在講解getAdaptiveExtensionClass().newInstance()這句代碼中的getAdaptiveExtensionClass(),此方法返回一個com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory類,以後來看一下其newInstance()代碼,調用這個方法,默認會執行AdaptiveExtensionFactory的無參構造器。這裏給出AdaptiveExtensionFactory的完整代碼:
1 package com.alibaba.dubbo.common.extension.factory; 2 3 import com.alibaba.dubbo.common.extension.Adaptive; 4 import com.alibaba.dubbo.common.extension.ExtensionFactory; 5 import com.alibaba.dubbo.common.extension.ExtensionLoader; 6 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.List; 10 11 /** 12 * AdaptiveExtensionFactory 13 */ 14 @Adaptive 15 public class AdaptiveExtensionFactory implements ExtensionFactory { 16 private final List<ExtensionFactory> factories; 17 18 /** 19 * 遍歷cachedClasses中緩存的extensionClasses的key,以後根據key來實例化對應的實現類,最後放置到EXTENSION_INSTANCES緩存中 20 */ 21 public AdaptiveExtensionFactory() { 22 ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); 23 List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); 24 for (String name : loader.getSupportedExtensions()) { 25 list.add(loader.getExtension(name)); 26 } 27 factories = Collections.unmodifiableList(list); 28 } 29 30 public <T> T getExtension(Class<T> type, String name) { 31 for (ExtensionFactory factory : factories) { 32 T extension = factory.getExtension(type, name); 33 if (extension != null) { 34 return extension; 35 } 36 } 37 return null; 38 } 39 }
從上能夠看出,這個裝飾類只是實例化好了各個ExtensionFactory(這裏是SpiExtensionFactory和SpringExtensionFactory),後續經過工廠獲取實現類實例都是由具體工廠來完成。
來看一下實例化代碼的地方,即loader.getExtension(name):
1 /** 2 * 從cachedInstances緩存中獲取name對應的實例,若是沒有,經過createExtension(name)建立,以後放入緩存 3 * getExtension(String name) 4 * --createExtension(String name) 5 * ----injectExtension(T instance) 6 */ 7 public T getExtension(String name) { 8 if (name == null || name.length() == 0) 9 throw new IllegalArgumentException("Extension name == null"); 10 if ("true".equals(name)) { 11 return getDefaultExtension(); 12 } 13 Holder<Object> holder = cachedInstances.get(name); 14 if (holder == null) { 15 cachedInstances.putIfAbsent(name, new Holder<Object>()); 16 holder = cachedInstances.get(name); 17 } 18 Object instance = holder.get(); 19 if (instance == null) { 20 synchronized (holder) { 21 instance = holder.get(); 22 if (instance == null) { 23 instance = createExtension(name); 24 holder.set(instance); 25 } 26 } 27 } 28 return (T) instance; 29 }
來看一下建立createExtension(name):
1 private T createExtension(String name) { 2 /** 從cachedClasses緩存中獲取全部的實現類map,以後經過name獲取到對應的實現類的Class對象 */ 3 Class<?> clazz = getExtensionClasses().get(name); 4 if (clazz == null) { 5 throw findException(name); 6 } 7 try { 8 /** 從EXTENSION_INSTANCES緩存中獲取對應的實現類的Class對象,若是沒有,直接建立,以後放入緩存 */ 9 T instance = (T) EXTENSION_INSTANCES.get(clazz); 10 if (instance == null) { 11 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance()); 12 instance = (T) EXTENSION_INSTANCES.get(clazz); 13 } 14 injectExtension(instance);//ioc 15 Set<Class<?>> wrapperClasses = cachedWrapperClasses; 16 if (wrapperClasses != null && wrapperClasses.size() > 0) { 17 for (Class<?> wrapperClass : wrapperClasses) { 18 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); 19 } 20 } 21 return instance; 22 } catch (Throwable t) { 23 throw new IllegalStateException("Extension instance(name: " + name + ", class: " + 24 type + ") could not be instantiated: " + t.getMessage(), t); 25 } 26 }
這裏,就體現出來了dubbo-SPI比JDK-SPI的好處:dubbo-SPI不須要遍歷全部的實現類來獲取想要的實現類,能夠直接經過name來獲取。
injectExtension(instance)和wrapper包裝功能後續再說。
到此爲止,ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);這行代碼的整個源碼就講述完成了。最後來看一下整個代碼的執行結果。
類變量
ExtensionLoader<Protocol> loader的實例變量:
總結:
第一點:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最終獲得的實例變量是:
第二點:ExtensionLoader<T>.getAdaptiveExtension()的調用層級
1 ExtensionLoader<T>.getAdaptiveExtension() 2 --createAdaptiveExtension() 3 ----injectExtension(getAdaptiveExtensionClass()) 4 ------getAdaptiveExtensionClass() 5 --------getExtensionClasses()//從spi文件中查找實現類上具備@Adaptive註解的類 6 ----------loadExtensionClasses() 7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir) 8 --------createAdaptiveExtensionClass()//若是從spi文件中沒有找到實現類上具備@Adaptive註解的類,則動態建立類
最終返回的是建立好的Adaptive類,例如AdaptiveExtensionFactory實例。
第三點:ExtensionLoader<T>.getExtension()的調用層級
1 ExtensionLoader<T>.getExtension() 2 --createExtension(String name) 3 ----getExtensionClasses().get(name)//獲取擴展類 4 ----injectExtension(instance);//ioc 5 ----wrapper包裝;//aop
最終返回的是建立好的具體實現類,例如SpringExtensionFactory實例。
至此,dubbo-spi源碼解析完成!!!