您好,登錄后才能下訂單哦!
這篇文章主要講解了“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴(lài)注入實(shí)例”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴(lài)注入實(shí)例”吧!
@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中有依賴(lài)AdaptiveExt類(lèi)型的變量 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"; } }
// 此時(shí)ThriftAdaptiveExt上面是標(biāo)注了@Adaptive注解的 @Adaptive public class ThriftAdaptiveExt implements AdaptiveExt { @Override public String echo(String msg, URL url) { return "thrift"; } }
Spring的IOC中
,給生成的bean注入依賴(lài),是調(diào)用context.getBean(name)
去獲得要注入的bean.Dubbo的IOC類(lèi)似,它通過(guò)ExtensionFactory
類(lèi)型的變量objectFactory
去dubbo中獲取bean,核心代碼objectFactory.getExtension(pt, property)
.下面先分析一下objectFactory
的創(chuàng)建過(guò)程.objectFactory
需要用到SpringExtensionFactory和SpiExtensionFactory
.先看一下ExtenionFactory
的實(shí)現(xiàn)類(lèi),如下圖.下面通過(guò)源碼分析objectFactory
的生成過(guò)程.
這里的getExtensionLoader()
詳細(xì)分析可以參見(jiàn): Dubbo的SPI機(jī)制分析1-SPI加載class
ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { // 刪去一些不必要的代碼,詳細(xì)分析可以看前面幾篇分析 // 從緩存中獲取與拓展類(lèi)對(duì)應(yīng)的ExtensionLoader ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { // 若緩存未命中,則創(chuàng)建一個(gè)新的實(shí)例,創(chuàng)建新的實(shí)例時(shí)會(huì)走 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,所以會(huì)執(zhí)行后面的代碼,加載并創(chuàng)建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 { // 創(chuàng)建自適應(yīng)拓展代理類(lèi)對(duì)象并放入緩存,這里創(chuàng)建的就是ExtensionFactory的自適應(yīng)拓展對(duì)象 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { // 拋異常 } } } } } return (T) instance; }
private T createAdaptiveExtension() { try { // 分為3步:1是創(chuàng)建自適應(yīng)拓展代理類(lèi)Class對(duì)象,2是通過(guò)反射創(chuàng)建對(duì)象,3是給創(chuàng)建的對(duì)象按需依賴(lài)注入 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { // 拋異常 } }
getExtensionClasses()
方法詳細(xì)分析可以參見(jiàn): Dubbo的SPI機(jī)制分析1-SPI加載class
private Class<?> getAdaptiveExtensionClass() { // 這里前面文章已經(jīng)分析過(guò)了,它會(huì)去加載默認(rèn)目錄下的ExtensionFactory的實(shí)現(xiàn)類(lèi),總共有3個(gè),目錄是 // META-INF/dubbo/internal/,該目錄對(duì)應(yīng)兩個(gè)文件,文件內(nèi)容見(jiàn)下,由于AdaptiveExtensionFactory上面 // 標(biāo)注了@Adaptive注解,所以它優(yōu)先級(jí)最高,它就是ExtensionFactory的默認(rèn)實(shí)現(xiàn)類(lèi) getExtensionClasses(); // 如果有標(biāo)注了@Adaptive注解實(shí)現(xiàn)類(lèi),那么cachedAdaptiveClass不為空,直接返回 if (cachedAdaptiveClass != null) { // 這里直接返回,cachedAdaptiveClass = AdaptiveExtensionFactory.class return cachedAdaptiveClass; } // 不會(huì)再走這一步 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }
文件1內(nèi)容: // 其中AdaptiveExtensionFactory上面標(biāo)注了@Adaptive注解 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory 文件2內(nèi)容: spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
@Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory {
// 分析完了getAdaptiveExtensionClass(),它是返回AdaptiveExtensionFactory,接下來(lái)newInstance會(huì)調(diào)用它默認(rèn)的構(gòu)造方法 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { // 里面維護(hù)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創(chuàng)建對(duì)象并放入list中 list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } }
// 上面已經(jīng)分析過(guò)了第一行代碼,這里面會(huì)創(chuàng)建ExtensionFactory類(lèi)型的變量objectFactory,這里面維護(hù)了一個(gè)list, // list里面有SpringExtensionFactory和SpiExtensionFactory類(lèi)型的實(shí)例,Dubbo的IOC獲取bean就是通過(guò)這兩個(gè)變量去獲取的 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) { // 創(chuàng)建拓展實(shí)例 instance = createExtension(name); holder.set(instance); } } } return (T) instance; }
private T createExtension(String name) { // 從配置文件中加載所有的拓展類(lèi),可得到“配置項(xiàng)名稱(chēng)”到“配置類(lèi)”的映射關(guān)系表 // 這里我們指定了名字dubbo,并不是通過(guò)getAdaptiveExtension方法去獲得自適應(yīng)拓展類(lèi),這點(diǎn)要區(qū)分 // 所以這里拿到的是com.alibaba.dubbo.demo.provider.adaptive.impl.DubboAdaptiveExt Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) { throw findException(name); } try { // 也是嘗試先從緩存獲取,獲取不到通過(guò)反射創(chuàng)建一個(gè)并放到緩存中 T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) { // 這里直接通過(guò)反射創(chuàng)建DubboAdaptiveExt的實(shí)例,然后給他依賴(lài)注入 EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 依賴(lài)注入 injectExtension(instance); return instance; } }
private T injectExtension(T instance) { // 這里為了排版好看,刪去一些異常捕捉拋出代碼 // objectFactory就是我們前面分析的,它里面維護(hù)了SpringExtensionFactory和SpiExtensionFactory類(lèi)型的實(shí)例 if (objectFactory != null) { // 遍歷DubboAdaptiveExt實(shí)例的所有方法,尋找set開(kāi)頭且參數(shù)為1個(gè),且方法權(quán)限為public的方法 for (Method method : instance.getClass().getMethods()) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { // 獲取參數(shù)類(lèi)型,這里是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類(lèi)型的名字為adaptiveExt的實(shí)例 Object object = objectFactory.getExtension(pt, property); // 獲取之后通過(guò)反射賦值 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; } }
這里獲取自適應(yīng)拓展可以參考: Dubbo的SPI機(jī)制分析2-Adaptive詳解
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怎么獲取,它是通過(guò)getAdaptiveExtension()去自適應(yīng)獲取,根本 // 沒(méi)有用到name,所以這里返回ThriftAdaptiveExt的實(shí)例 return loader.getAdaptiveExtension(); } } return null; } }
public class SpringExtensionFactory implements ExtensionFactory { // 可以看到Spring是先根據(jù)名字去取,取不到再根據(jù)類(lèi)型去取 @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); }
/** * 測(cè)試通過(guò)URL依賴(lài)注入,將ThriftAdaptiveExt類(lèi)上面的注解注釋掉,同時(shí)給AdaptiveExt方法加上注解@Adaptive("t") */ @Test public void test5(){ ExtensionLoader<AdaptiveExt> loader = ExtensionLoader.getExtensionLoader(AdaptiveExt.class); Map<String, String> map = new HashMap<>(); // t這個(gè)key就是根據(jù)@Adaptive("t")定的,兩者要一致 map.put("t", "cloud"); URL url = new URL("", "", 1, map); AdaptiveExt adaptiveExtension = loader.getExtension("dubbo"); adaptiveExtension.echo(" ", url); }
上述代碼輸出spring cloud,創(chuàng)建完DubboAdaptiveExt的實(shí)例給其注入依賴(lài)時(shí),調(diào)用injectExtension(instance)
,因?yàn)闆](méi)有了@Adaptive標(biāo)注的類(lèi),所以需要Dubbo自己生成自適應(yīng)拓展代理類(lèi)Class,生成過(guò)程可以參考: Dubbo的SPI機(jī)制分析2-Adaptive詳解.生成的代理類(lèi)中有這樣一句關(guān)鍵代碼: String extName = url.getParameter("t", "dubbo")
,因?yàn)閡rl中有這個(gè)t參數(shù),所以最后會(huì)調(diào)用cloud所對(duì)應(yīng)的SpringCloudAdaptiveExt的echo方法,輸出spring cloud.
感謝各位的閱讀,以上就是“Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴(lài)注入實(shí)例”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Dubbo的SPI機(jī)制介紹以及Dubbo的IOC依賴(lài)注入實(shí)例這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。