Spring框架核心源代码的分析及其体味-3
Spring框架核心源代码的分析及其感受-3
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException { XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory); //从这块代码 可以发现XML的解析估计是在这里发生的,也就是这个Reader来读取的, .... loadBeanDefinitions(beanDefinitionReader); } …. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { Resource[] configResources = getConfigResources(); if (configResources != null) { reader.loadBeanDefinitions(configResources); //果然是由Reader来加载和解析XML并载入BeanDefinition中的! } String[] configLocations = getConfigLocations(); if (configLocations != null) { reader.loadBeanDefinitions(configLocations); } }
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { int validationMode = getValidationModeForResource(resource); Document doc = this.documentLoader.loadDocument( inputSource, getEntityResolver(), this.errorHandler, validationMode, isNamespaceAware()); //在这里激发注册过程 return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { … }
从上上面的代码中,你可以肯定的是 XML 是在 XmlBeanDefinitionReader 类中解析的,解析到 BeanDefinition 中!进入 XmlBeanDefinitionReader 中,看一看:
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { Assert.notNull(encodedResource, "EncodedResource must not be null"); if (logger.isInfoEnabled()) { logger.info("Loading XML bean definitions from " + encodedResource.getResource()); } Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get(); if (currentResources == null) { currentResources = new HashSet<EncodedResource>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { InputStream inputStream = encodedResource.getResource().getInputStream(); try { InputSource inputSource = new InputSource(inputStream); if (encodedResource.getEncoding() != null) { inputSource.setEncoding(encodedResource.getEncoding()); } //这里是具体加载的实现逻辑 return doLoadBeanDefinitions(inputSource, encodedResource.getResource()); ...... }
哈哈,你也可以看到 ReaourceLoader 确实是加载 XML 的!进入 doLoadBeanDefinitions 方法!
-------------TODO,这里需要补充一下
--------------------------------------------------------------------
看到了吧?就是一个大家经常用到 SAX 的 Document 来取得 XML 文档的,在进入 registerBeanDefinitions 看看!
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException { BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader(); if (documentReader instanceof DefaultBeanDefinitionDocumentReader) { ((DefaultBeanDefinitionDocumentReader)documentReader).setEnvironment(this.getEnvironment()); } int countBefore = getRegistry().getBeanDefinitionCount(); documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//在这里注册,也就是注册到一个共享的容器中,比如Map.这样缓存起来后,spring其他部分就可以从一个共享的位置加载目标BeanDefinition了(通过BeanDefinition的名字)。 return getRegistry().getBeanDefinitionCount() - countBefore; }
在进入 documentReader.registerBeanDefinitions 看看!
protected void doRegisterBeanDefinitions(Element root) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); boolean isCandidate = false; if (profileSpec == null || profileSpec.equals("")) { isCandidate = true; } else { String[] profiles = commaDelimitedListToStringArray(trimAllWhitespace(profileSpec)); for (String profile : profiles) { if (this.environment.getActiveProfiles().contains(profile)) { isCandidate = true; break; } } } if (!isCandidate) { return; } BeanDefinitionParserDelegate parent = this.delegate;//Deletgate里面包含着多有XML属性和elemnt的结构信息 this.delegate = createHelper(readerContext, root, parent); preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root);