摘要:屬性上篇文章中,提到在獲取擴展點接口對應的的時候,會執行私有構造函數。因為此時是,即當為時,即我們可以看出,所有非擴展點接口都會執行對應的實例的方法返回一個實例,即對象。
spring是如何獲得容器中管理的類的
拿到applicationContext,就可以調用getBean方法來獲得Spring的bean對象了
public class SpringContextUtil implements ApplicationContextAware { // Spring應用上下文環境 private static ApplicationContext applicationContext; /** * 實現ApplicationContextAware接口的回調方法,設置上下文環境 * * @param applicationContext */ public void setApplicationContext(ApplicationContext applicationContext) { SpringContextUtil.applicationContext = applicationContext; } /** * @return ApplicationContext */ public static ApplicationContext getApplicationContext() { return applicationContext; } /** * 獲取對象 * * @param name * @return Object * @throws BeansException */ public static Object getBean(String name) throws BeansException { return applicationContext.getBean(name); } }dubbo擴展點的IOC 前文中,大致有提到一些有關IOC
第一點 在講解ExtensionLoader源碼的構造函數的時候,我們說過,每一個ExtensionLoader實例都有一個 objectFactory 屬性,他是實現Ioc的關鍵;
第二點 相比較于JDK的SPI機制,dubbo的SPI機制支持擴展通過setter的方式來注入其他擴展點。
第三點 在調用ExtensionLoader的getExtension方法時,在獲取了相應的class并創建了instance之后,通過injectExtension(intance)方法來通過setter的方式來注入其他擴展點。
第四點 loadFile函數解析SPI配置時,假如這個類帶@Adaptive注解,緩存到cachedAdaptiveClass。
如何實現IOC -> ExtensionLoader的injectExtension方法源碼關鍵說明,
獲取instance的所有方法,并解析以set方法開頭的方法,例如setXxyy(Xxyy xxyy)。
拿到set方法的入參類型Xxyy、屬性名xxyy。
執行objectFactory.getExtension(pt, property)拿到Xxyy對應的實例。
通過反射執行set方法,注入Xxyy對象。
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; }
通過上面的方法,就可以將屬性注入到instance中,實現自動裝配(IOC)。下面我們來看一下 objectFactory.getExtension(pt, property)是如何工作的。objectFactory屬性
上篇文章中,提到在獲取Container擴展點接口對應的ExtensionLoader的時候,會執行私有ExtensionLoader構造函數。
private ExtensionLoader(Class> type) { this.type = type; objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); }
因為此時type是Container.class,即objectFactory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension(); 當type為ExtensionFactory.class時,即 objectFactory = null. 我們可以看出,所有非ExtensionFactory.class擴展點接口都會執行ExtensionFactory對應的ExtensionLoader實例的getAdaptiveExtension()方法返回一個ExtensionFactory實例,即objectFactory對象。否則,objectFactory對象為null。核心方法 -> ExtensionLoader的getAdaptiveExtension方法源碼
getAdaptiveExtension 獲取帶有Adaptive注解的擴展實現類
createAdaptiveExtension()創建實例
injectExtension() 自動注入IOC
getAdaptiveExtensionClass() ---執行cachedAdaptiveClass對象的構造函數
getExtensionClasses() ---解析所有的擴展點實現
loadExtensionClasses() ---加載擴展類
loadFile() --- 從固定的文件路徑,解析加載對應的擴展點實現【上一篇已經說過,這個地方會加載幾種情形的擴展實現類,包括拿到cachedAdaptiveClass對象】
返回cachedAdaptiveClass --- 返回loadFile()方法中構造的cachedAdaptiveClass對象
執行 cachedAdaptiveClass.newInstance() ---執行AdaptiveExtensionFactory的構造函數
ExtensionFactory的實現類AdaptiveExtensionFactory帶有Adaptive標簽,另外兩個實現類SpiExtensionFactory、SpringExtensionFactory就是正常的實現類,也是我們見的最多的那種擴展點實現類。
### AdaptiveExtensionFactory源碼 關鍵說明, 1. factories屬性,所有的非@Adaptive類的ExtensionFactory實例的集合,以后所有與ExtensionFactory打交道的操作都交給AdaptiveExtensionFactory, 2. injectExtension方法中,調用的 Object object = objectFactory.getExtension(pt, property);分別調用SpiExtensionFactory、SpringExtensionFactory兩個實際的實現類。 /** * AdaptiveExtensionFactory * * @author william.liangf */ @Adaptive public class AdaptiveExtensionFactory implements ExtensionFactory { //所有的非@Adaptive類的ExtensionFactory實例的集合 private final ListSpringExtensionFactory源碼factories; //因為ExtensionFactory對應的ExtensionLoader實例中緩存字段已經初始化好了,所以的ExtensionLoader的操作大都是從緩存中獲取的數據 public AdaptiveExtensionFactory() { //從緩存的static變量EXTENSION_LOADERS中拿到ExtensionFactory對應的ExtensionLoader實例 ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List list = new ArrayList (); //拿到loader中加載的普通的SPI擴展接口實現類的名稱,spring與spi // adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory // spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory for (String name : loader.getSupportedExtensions()) { //根據名稱創建對應的ExtensionFactory實例 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; } }
是不是有一點熟悉的味道了啊,這也算是一個首尾呼應吧~
這一篇到時很快就寫完了~ 下篇文章會講解擴展點是如何實現AOP的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/69057.html
摘要:要構建自適應實例,先要有自適應的實現類,實現類有兩種方式一種通過配置文件,一種是通過是字節碼的方式動態生成。 SPI機制 SPI,即(service provider interface)機制,有很多組件的實現,如日志、數據庫訪問等都是采用這樣的方式,一般通用組件為了提升可擴展性,基于接口編程,將操作接口形成標準規范,但是可以開放多種擴展實現,這種做法也符合開閉設計原則,使組件具有可插...
摘要:今天我想聊聊的另一個很棒的特性就是它的可擴展性。的擴展機制在的官網上,描述自己是一個高性能的框架。接下來的章節中我們會慢慢揭開擴展機制的神秘面紗。擴展擴展點的實現類。的定義在配置文件中可以看到文件中定義了個的擴展實現。 摘要: 在Dubbo的官網上,Dubbo描述自己是一個高性能的RPC框架。今天我想聊聊Dubbo的另一個很棒的特性, 就是它的可擴展性。 Dubbo的擴展機制 在Dub...
摘要:在中配置,以配置為例整個,最先使用的地方從里面讀取這個配置使用接口的中獲取具體的實現類中有兩個值當主線程被外部終止時,會觸發,執行的與方法通知下面的鎖操作,主線程正常走完代碼,并最終停止。 spring是如何啟動容器的 常見的一種在本地使用main方法啟動spring的方法 public static void main(String[] args) throws Except...
摘要:為了實現在模塊裝配的時候,不在模塊里寫死代碼,就需要一種服務發現機制。就提供了這樣一種機制為某個接口尋找服務實現,有點類似思想,將裝配的控制權移到代碼之外。即接口文件的全類名。五示例遵循上述第一條第點,這里為接口文件,其中和為兩個實現類。 一、Dubbo內核 Dubbo內核主要包含SPI、AOP、IOC、Compiler。 二、JDK的SPI 1.spi的設計目標: 面向對象的設計里...
摘要:什么是類那什么樣類的才是擴展機制中的類呢類是一個有復制構造函數的類,也是典型的裝飾者模式。代碼如下有一個參數是的復制構造函數有一個構造函數,參數是擴展點,所以它是一個擴展機制中的類。 摘要:?在Dubbo可擴展機制實戰中,我們了解了Dubbo擴展機制的一些概念,初探了Dubbo中LoadBalance的實現,并自己實現了一個LoadBalance。是不是覺得Dubbo的擴展機制很不錯呀...
閱讀 2618·2021-11-12 10:36
閱讀 2257·2021-08-23 09:47
閱讀 1675·2019-08-30 15:44
閱讀 1400·2019-08-30 14:10
閱讀 2241·2019-08-29 16:52
閱讀 2333·2019-08-29 16:40
閱讀 1582·2019-08-29 16:17
閱讀 2407·2019-08-26 13:21