摘要:屬性上篇文章中,提到在獲取擴(kuò)展點(diǎn)接口對(duì)應(yīng)的的時(shí)候,會(huì)執(zhí)行私有構(gòu)造函數(shù)。因?yàn)榇藭r(shí)是,即當(dāng)為時(shí),即我們可以看出,所有非擴(kuò)展點(diǎn)接口都會(huì)執(zhí)行對(duì)應(yīng)的實(shí)例的方法返回一個(gè)實(shí)例,即對(duì)象。
spring是如何獲得容器中管理的類的
拿到applicationContext,就可以調(diào)用getBean方法來(lái)獲得Spring的bean對(duì)象了
public class SpringContextUtil implements ApplicationContextAware { // Spring應(yīng)用上下文環(huán)境 private static ApplicationContext applicationContext; /** * 實(shí)現(xiàn)ApplicationContextAware接口的回調(diào)方法,設(shè)置上下文環(huán)境 * * @param applicationContext */ public void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtil.applicationContext = applicationContext; } /** * @return ApplicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 獲取對(duì)象 * * @param name * @return Object * @throws BeansException */ public static Object getBean(String name) throws BeansException { return applicationContext.getBean(name); } }dubbo擴(kuò)展點(diǎn)的IOC 前文中,大致有提到一些有關(guān)IOC
第一點(diǎn) 在講解ExtensionLoader源碼的構(gòu)造函數(shù)的時(shí)候,我們說(shuō)過(guò),每一個(gè)ExtensionLoader實(shí)例都有一個(gè) objectFactory 屬性,他是實(shí)現(xiàn)Ioc的關(guān)鍵;
第二點(diǎn) 相比較于JDK的SPI機(jī)制,dubbo的SPI機(jī)制支持?jǐn)U展通過(guò)setter的方式來(lái)注入其他擴(kuò)展點(diǎn)。
第三點(diǎn) 在調(diào)用ExtensionLoader的getExtension方法時(shí),在獲取了相應(yīng)的class并創(chuàng)建了instance之后,通過(guò)injectExtension(intance)方法來(lái)通過(guò)setter的方式來(lái)注入其他擴(kuò)展點(diǎn)。
第四點(diǎn) loadFile函數(shù)解析SPI配置時(shí),假如這個(gè)類帶@Adaptive注解,緩存到cachedAdaptiveClass。
如何實(shí)現(xiàn)IOC -> ExtensionLoader的injectExtension方法源碼關(guān)鍵說(shuō)明,
獲取instance的所有方法,并解析以set方法開(kāi)頭的方法,例如setXxyy(Xxyy xxyy)。
拿到set方法的入?yún)㈩愋蚗xyy、屬性名xxyy。
執(zhí)行objectFactory.getExtension(pt, property)拿到Xxyy對(duì)應(yīng)的實(shí)例。
通過(guò)反射執(zhí)行set方法,注入Xxyy對(duì)象。
private T injectExtension(T instance) { try { if (objectFactory != null) { for (Method method : instance.getClass().getMethods()) { if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { Class> pt = method.getParameterTypes()[0]; try { String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; Object object = objectFactory.getExtension(pt, property); if (object != null) { method.invoke(instance, object); } } catch (Exception e) { logger.error("fail to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; }
通過(guò)上面的方法,就可以將屬性注入到instance中,實(shí)現(xiàn)自動(dòng)裝配(IOC)。下面我們來(lái)看一下 objectFactory.getExtension(pt, property)是如何工作的。objectFactory屬性
上篇文章中,提到在獲取Container擴(kuò)展點(diǎn)接口對(duì)應(yīng)的ExtensionLoader的時(shí)候,會(huì)執(zhí)行私有ExtensionLoader構(gòu)造函數(shù)。
private ExtensionLoader(Class> type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }
因?yàn)榇藭r(shí)type是Container.class,即objectFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); 當(dāng)type為ExtensionFactory.class時(shí),即 objectFactory = null. 我們可以看出,所有非ExtensionFactory.class擴(kuò)展點(diǎn)接口都會(huì)執(zhí)行ExtensionFactory對(duì)應(yīng)的ExtensionLoader實(shí)例的getAdaptiveExtension()方法返回一個(gè)ExtensionFactory實(shí)例,即objectFactory對(duì)象。否則,objectFactory對(duì)象為null。核心方法 -> ExtensionLoader的getAdaptiveExtension方法源碼
getAdaptiveExtension 獲取帶有Adaptive注解的擴(kuò)展實(shí)現(xiàn)類
createAdaptiveExtension()創(chuàng)建實(shí)例
injectExtension() 自動(dòng)注入IOC
getAdaptiveExtensionClass() ---執(zhí)行cachedAdaptiveClass對(duì)象的構(gòu)造函數(shù)
getExtensionClasses() ---解析所有的擴(kuò)展點(diǎn)實(shí)現(xiàn)
loadExtensionClasses() ---加載擴(kuò)展類
loadFile() --- 從固定的文件路徑,解析加載對(duì)應(yīng)的擴(kuò)展點(diǎn)實(shí)現(xiàn)【上一篇已經(jīng)說(shuō)過(guò),這個(gè)地方會(huì)加載幾種情形的擴(kuò)展實(shí)現(xiàn)類,包括拿到cachedAdaptiveClass對(duì)象】
返回cachedAdaptiveClass --- 返回loadFile()方法中構(gòu)造的cachedAdaptiveClass對(duì)象
執(zhí)行 cachedAdaptiveClass.newInstance() ---執(zhí)行AdaptiveExtensionFactory的構(gòu)造函數(shù)
ExtensionFactory的實(shí)現(xiàn)類AdaptiveExtensionFactory帶有Adaptive標(biāo)簽,另外兩個(gè)實(shí)現(xiàn)類SpiExtensionFactory、SpringExtensionFactory就是正常的實(shí)現(xiàn)類,也是我們見(jiàn)的最多的那種擴(kuò)展點(diǎn)實(shí)現(xiàn)類。
### AdaptiveExtensionFactory源碼 關(guān)鍵說(shuō)明, 1. factories屬性,所有的非@Adaptive類的ExtensionFactory實(shí)例的集合,以后所有與ExtensionFactory打交道的操作都交給AdaptiveExtensionFactory, 2. injectExtension方法中,調(diào)用的 Object object = objectFactory.getExtension(pt, property);分別調(diào)用SpiExtensionFactory、SpringExtensionFactory兩個(gè)實(shí)際的實(shí)現(xiàn)類。 /** * AdaptiveExtensionFactory * * @author william.liangf */ @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { //所有的非@Adaptive類的ExtensionFactory實(shí)例的集合 private final ListSpringExtensionFactory源碼factories; //因?yàn)镋xtensionFactory對(duì)應(yīng)的ExtensionLoader實(shí)例中緩存字段已經(jīng)初始化好了,所以的ExtensionLoader的操作大都是從緩存中獲取的數(shù)據(jù) public AdaptiveExtensionFactory() { //從緩存的static變量EXTENSION_LOADERS中拿到ExtensionFactory對(duì)應(yīng)的ExtensionLoader實(shí)例 ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List list = new ArrayList (); //拿到loader中加載的普通的SPI擴(kuò)展接口實(shí)現(xiàn)類的名稱,spring與spi // adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory // spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory for (String name : loader.getSupportedExtensions()) { //根據(jù)名稱創(chuàng)建對(duì)應(yīng)的ExtensionFactory實(shí)例 list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } public T getExtension(Class type, String name) { for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; } }
public class SpringExtensionFactory implements ExtensionFactory { private static final Setcontexts = new ConcurrentHashSet (); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); } public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } @SuppressWarnings("unchecked") public T getExtension(Class type, String name) { for (ApplicationContext context : contexts) { if (context.containsBean(name)) { Object bean = context.getBean(name); if (type.isInstance(bean)) { return (T) bean; } } } return null; } }
是不是有一點(diǎn)熟悉的味道了啊,這也算是一個(gè)首尾呼應(yīng)吧~
這一篇到時(shí)很快就寫完了~ 下篇文章會(huì)講解擴(kuò)展點(diǎn)是如何實(shí)現(xiàn)AOP的。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69057.html
摘要:要構(gòu)建自適應(yīng)實(shí)例,先要有自適應(yīng)的實(shí)現(xiàn)類,實(shí)現(xiàn)類有兩種方式一種通過(guò)配置文件,一種是通過(guò)是字節(jié)碼的方式動(dòng)態(tài)生成。 SPI機(jī)制 SPI,即(service provider interface)機(jī)制,有很多組件的實(shí)現(xiàn),如日志、數(shù)據(jù)庫(kù)訪問(wèn)等都是采用這樣的方式,一般通用組件為了提升可擴(kuò)展性,基于接口編程,將操作接口形成標(biāo)準(zhǔn)規(guī)范,但是可以開(kāi)放多種擴(kuò)展實(shí)現(xiàn),這種做法也符合開(kāi)閉設(shè)計(jì)原則,使組件具有可插...
摘要:今天我想聊聊的另一個(gè)很棒的特性就是它的可擴(kuò)展性。的擴(kuò)展機(jī)制在的官網(wǎng)上,描述自己是一個(gè)高性能的框架。接下來(lái)的章節(jié)中我們會(huì)慢慢揭開(kāi)擴(kuò)展機(jī)制的神秘面紗。擴(kuò)展擴(kuò)展點(diǎn)的實(shí)現(xiàn)類。的定義在配置文件中可以看到文件中定義了個(gè)的擴(kuò)展實(shí)現(xiàn)。 摘要: 在Dubbo的官網(wǎng)上,Dubbo描述自己是一個(gè)高性能的RPC框架。今天我想聊聊Dubbo的另一個(gè)很棒的特性, 就是它的可擴(kuò)展性。 Dubbo的擴(kuò)展機(jī)制 在Dub...
摘要:在中配置,以配置為例整個(gè),最先使用的地方從里面讀取這個(gè)配置使用接口的中獲取具體的實(shí)現(xiàn)類中有兩個(gè)值當(dāng)主線程被外部終止時(shí),會(huì)觸發(fā),執(zhí)行的與方法通知下面的鎖操作,主線程正常走完代碼,并最終停止。 spring是如何啟動(dòng)容器的 常見(jiàn)的一種在本地使用main方法啟動(dòng)spring的方法 public static void main(String[] args) throws Except...
摘要:為了實(shí)現(xiàn)在模塊裝配的時(shí)候,不在模塊里寫死代碼,就需要一種服務(wù)發(fā)現(xiàn)機(jī)制。就提供了這樣一種機(jī)制為某個(gè)接口尋找服務(wù)實(shí)現(xiàn),有點(diǎn)類似思想,將裝配的控制權(quán)移到代碼之外。即接口文件的全類名。五示例遵循上述第一條第點(diǎn),這里為接口文件,其中和為兩個(gè)實(shí)現(xiàn)類。 一、Dubbo內(nèi)核 Dubbo內(nèi)核主要包含SPI、AOP、IOC、Compiler。 二、JDK的SPI 1.spi的設(shè)計(jì)目標(biāo): 面向?qū)ο蟮脑O(shè)計(jì)里...
摘要:什么是類那什么樣類的才是擴(kuò)展機(jī)制中的類呢類是一個(gè)有復(fù)制構(gòu)造函數(shù)的類,也是典型的裝飾者模式。代碼如下有一個(gè)參數(shù)是的復(fù)制構(gòu)造函數(shù)有一個(gè)構(gòu)造函數(shù),參數(shù)是擴(kuò)展點(diǎn),所以它是一個(gè)擴(kuò)展機(jī)制中的類。 摘要:?在Dubbo可擴(kuò)展機(jī)制實(shí)戰(zhàn)中,我們了解了Dubbo擴(kuò)展機(jī)制的一些概念,初探了Dubbo中LoadBalance的實(shí)現(xiàn),并自己實(shí)現(xiàn)了一個(gè)LoadBalance。是不是覺(jué)得Dubbo的擴(kuò)展機(jī)制很不錯(cuò)呀...
閱讀 2627·2021-11-12 10:36
閱讀 2267·2021-08-23 09:47
閱讀 1689·2019-08-30 15:44
閱讀 1411·2019-08-30 14:10
閱讀 2249·2019-08-29 16:52
閱讀 2347·2019-08-29 16:40
閱讀 1594·2019-08-29 16:17
閱讀 2415·2019-08-26 13:21