拿到applicationContext,就能夠調用getBean方法來得到Spring的bean對象了java
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); } }
關鍵說明,spring
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)是如何工做的。
上篇文章中,提到在獲取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。
getAdaptiveExtension 獲取帶有Adaptive註解的擴展實現類緩存
createAdaptiveExtension()建立實例app
injectExtension() 自動注入IOC函數
getAdaptiveExtensionClass() ---執行cachedAdaptiveClass對象的構造函數this
getExtensionClasses() ---解析全部的擴展點實現code
loadExtensionClasses() ---加載擴展類對象
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 List<ExtensionFactory> factories; //由於ExtensionFactory對應的ExtensionLoader實例中緩存字段已經初始化好了,因此的ExtensionLoader的操做大都是從緩存中獲取的數據 public AdaptiveExtensionFactory() { //從緩存的static變量EXTENSION_LOADERS中拿到ExtensionFactory對應的ExtensionLoader實例 ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); List<ExtensionFactory> list = new ArrayList<ExtensionFactory>(); //拿到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> T getExtension(Class<T> 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 Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>(); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); } public static void removeApplicationContext(ApplicationContext context) { contexts.remove(context); } @SuppressWarnings("unchecked") 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; } } } return null; } }
是否是有一點熟悉的味道了啊,這也算是一個首尾呼應吧~rem
這一篇到時很快就寫完了~ 下篇文章會講解擴展點是如何實現AOP的。