@Test public void test1(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); URL url = URL.valueOf("test://localhost/test"); adaptiveExtension.echo("d", url); } public class DubboAdaptiveExt implements AdaptiveExt { // dubbo中有依賴AdaptiveExt類型的變量 private AdaptiveExt adaptiveExt; public void setAdaptiveExt(AdaptiveExt adaptiveExt) { this.adaptiveExt = adaptiveExt; } @Override public String echo(String msg, URL url) { System.out.println(this.adaptiveExt.echo(msg, url)); return "dubbo"; } }
// 此時ThriftAdaptiveExt上面是標註了@Adaptive註解的 @Adaptive public class ThriftAdaptiveExt implements AdaptiveExt { @Override public String echo(String msg, URL url) { return "thrift"; } }
Spring的IOC中,給生成的bean注入依賴,是調用context.getBean(name)去得到要注入的bean.Dubbo的IOC相似,它經過ExtensionFactory類型的變量objectFactory去dubbo中獲取bean,核心代碼objectFactory.getExtension(pt, property)
.下面先分析一下objectFactory的建立過程.objectFactory須要用到SpringExtensionFactory和SpiExtensionFactory
.先看一下ExtenionFactory的實現類,以下圖.下面經過源碼分析objectFactory的生成過程.spring
這裏的getExtensionLoader()詳細分析能夠參見: Dubbo的SPI機制1-SPI簡單分析segmentfault
ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { // 刪去一些沒必要要的代碼,詳細分析能夠看前面幾篇分析 // 從緩存中獲取與拓展類對應的ExtensionLoader ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { // 若緩存未命中,則建立一個新的實例,建立新的實例時會走 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; } private ExtensionLoader(Class<?> type) { this.type = type; // 這裏的type是AdaptiveExt.class,因此會執行後面的代碼,加載並建立SpiExtensionFactory // 和SpringExtensionFactory objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }
public T getAdaptiveExtension() { Object instance = cachedAdaptiveInstance.get(); if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 建立自適應拓展代理類對象並放入緩存,這裏建立的就是ExtensionFactory的自適應拓展對象 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { // 拋異常 } } } } } return (T) instance; }
private T createAdaptiveExtension() { try { // 分爲3步:1是建立自適應拓展代理類Class對象,2是經過反射建立對象,3是給建立的對象按需依賴注入 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { // 拋異常 } }
getExtensionClasses()方法詳細分析能夠參見: Dubbo的SPI機制1-SPI簡單分析緩存
private Class<?> getAdaptiveExtensionClass() { // 這裏前面文章已經分析過了,它會去加載默認目錄下的ExtensionFactory的實現類,總共有3個,目錄是 // META-INF/dubbo/internal/,該目錄對應兩個文件,文件內容見下,因爲AdaptiveExtensionFactory上面 // 標註了@Adaptive註解,因此它優先級最高,它就是ExtensionFactory的默認實現類 getExtensionClasses(); // 若是有標註了@Adaptive註解實現類,那麼cachedAdaptiveClass不爲空,直接返回 if (cachedAdaptiveClass != null) { // 這裏直接返回,cachedAdaptiveClass = AdaptiveExtensionFactory.class return cachedAdaptiveClass; } // 不會再走這一步 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }
文件1內容: // 其中AdaptiveExtensionFactory上面標註了@Adaptive註解 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 文件2內容: spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory {
// 分析完了getAdaptiveExtensionClass(),它是返回AdaptiveExtensionFactory,接下來newInstance會 // 調用它默認的構造方法 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { // 裏面維護SpringExtensionFactory和SpiExtensionFactory private final List<ExtensionFactory> factories; public AdaptiveExtensionFactory() { ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); for (String name : loader.getSupportedExtensions()) { // 分別給SpringExtensionFactory和SpiExtensionFactory建立對象並放入list中 list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } }
// 上面已經分析過了第一行代碼,這裏面會建立ExtensionFactory類型的變量objectFactory,這裏面維護了一個list, // list裏面有SpringExtensionFactory和SpiExtensionFactory類型的實例,Dubbo的IOC獲取bean就是經過這兩個 // 變量去獲取的 ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); public T getExtension(String name) { // 刪去一些代碼 if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { // 建立拓展實例 instance = createExtension(name); holder.set(instance); } } } return (T) instance; }
private T createExtension(String name) { // 從配置文件中加載全部的拓展類,可獲得「配置項名稱」到「配置類」的映射關係表 // 這裏咱們指定了名字dubbo,並非經過getAdaptiveExtension方法去得到自適應拓展類,這點要區分 // 因此這裏拿到的是com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 也是嘗試先從緩存獲取,獲取不到經過反射建立一個並放到緩存中 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { // 這裏直接經過反射建立DubboAdaptiveExt的實例,而後給他依賴注入 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 依賴注入 injectExtension(instance); return instance; } }
private T injectExtension(T instance) { // 這裏爲了排版好看,刪去一些異常捕捉拋出代碼 // objectFactory就是咱們前面分析的,它裏面維護了SpringExtensionFactory和SpiExtensionFactory類型的實例 if (objectFactory != null) { // 遍歷DubboAdaptiveExt實例的全部方法,尋找set開頭且參數爲1個,且方法權限爲public的方法 for (Method method : instance.getClass().getMethods()) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { // 獲取參數類型,這裏是AdaptiveExt.class Class<?> pt = method.getParameterTypes()[0]; // 獲取屬性名,這裏是adaptiveExt String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; // 獲取容器中AdaptiveExt.class類型的名字爲adaptiveExt的實例 Object object = objectFactory.getExtension(pt, property); // 獲取以後經過反射賦值 if (object != null) { method.invoke(instance, object); } } } } return instance; }
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { private final List<ExtensionFactory> factories; @Override public <T> T getExtension(Class<T> type, String name) { // 遍歷factory中全部的ExtensionFactory,先從SpiExtensionFactory中獲取,獲取不到在去Spring容器中獲取 for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; } }
這裏獲取自適應拓展能夠參考: Dubbo的SPI機制分析2-Adaptive詳解ide
public class SpiExtensionFactory implements ExtensionFactory { @Override public <T> T getExtension(Class<T> type, String name) { if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type); if (!loader.getSupportedExtensions().isEmpty()) { // 先看SpiExtensionFactory怎麼獲取,它是經過getAdaptiveExtension()去自適應獲取,根本 // 沒有用到name,因此這裏返回ThriftAdaptiveExt的實例 return loader.getAdaptiveExtension(); } } return null; } }
public class SpringExtensionFactory implements ExtensionFactory { // 能夠看到Spring是先根據名字去取,取不到再根據類型去取 @Override public <T> T getExtension(Class<T> type, String name) { for (ApplicationContext context : contexts) { if (context.containsBean(name)) { Object bean = context.getBean(name); if (type.isInstance(bean)) { return (T) bean; } } } for (ApplicationContext context : contexts) { try { return context.getBean(type); } } return null; } }
// 因此這段代碼輸出:thrift @Test public void test1(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); URL url = URL.valueOf("test://localhost/test"); adaptiveExtension.echo("d", url); }
/** * 測試經過URL依賴注入,將ThriftAdaptiveExt類上面的註解註釋掉,同時給AdaptiveExt方法加上註解@Adaptive("t") */ @Test public void test5(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); Map<String, String> map = new HashMap<>(); // t這個key就是根據@Adaptive("t")定的,二者要一致 map.put("t", "cloud"); URL url = new URL("", "", 1, map); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); adaptiveExtension.echo(" ", url); }
上述代碼輸出spring cloud,建立完DubboAdaptiveExt的實例給其注入依賴時,調用injectExtension(instance),由於沒有了@Adaptive標註的類,因此須要Dubbo本身生成自適應拓展代理類Class,生成過程能夠參考: Dubbo的SPI機制分析2-Adaptive詳解.生成的代理類中有這樣一句關鍵代碼: String extName = url.getParameter("t", "dubbo")
,由於url中有這個t參數,因此最後會調用cloud所對應的SpringCloudAdaptiveExt的echo方法,輸出spring cloud.源碼分析