XmlBeanDefinitionReader: 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(); / / note resourcesCurrentlyBeingLoaded is a ThreadLocal variables, 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()); BeanDefinition} finally {inputstream.close (); } } catch (IOException ex) { throw new BeanDefinitionStoreException( "IOException parsing XML document from " + encodedResource.getResource(), ex); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); }}}Copy the code
This method is used to load the bean definition from the specified XML file.
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try { Document doc = doLoadDocument(inputSource, resource); Return registerBeanDefinitions(doc, resource); } catch (BeanDefinitionStoreException ex) { throw ex; } catch (SAXParseException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex); } catch (SAXException ex) { throw new XmlBeanDefinitionStoreException(resource.getDescription(), "XML document from " + resource + " is invalid", ex); } catch (ParserConfigurationException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Parser configuration exception parsing XML from " + resource, ex); } catch (IOException ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "IOException parsing XML document from " + resource, ex); } catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); }}Copy the code
This method actually loads the bean definition from the specified XML file.
@SuppressWarnings("deprecation")
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
documentReader.setEnvironment(getEnvironment());
int countBefore = getRegistry().getBeanDefinitionCount();
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
Copy the code
Registering a bean definition included in a given DOM document is called by loadBeanDefinitions to create and invoke a new instance of the parser class
BeanDefinitionDocumentReader this interface used to resolve XML document contains Spring bean definition of SPI. The XmlBeanDefinitionReader is used to actually parse the DOM document. The implementation class is DefaultBeanDefinitionDocumentReader.
DefaultBeanDefinitionDocumentReader class registerBeanDefinitions methods according to “spring – beans” XSD parsing bean definition, open a DOM document; Then initialize the default Settings specified at the Beans level; The contained bean definition is then parsed.
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
Copy the code
Register each bean definition in the given root {@code} element.
Protected void doRegisterBeanDefinitions Element (root) {/ / any nested < beans > Element will lead to the method of recursion. // In order to properly propagate and preserve the <beans> default-* attribute, trace the current delegate, which may be empty. // Create a new (child) delegate with a reference to the parent for fallback purposes, and then finally reset this.delegate to its original (parent) reference. // This behavior simulates a bunch of delegates without actually needing one. BeanDefinitionParserDelegate parent = this.delegate; this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) { String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); if (StringUtils.hasText(profileSpec)) { String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); if (! getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { return; }} // The classic template method pattern preProcessXml(root); And postProcessXml (root); Are empty implementations on which subclasses can implement custom extensions preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); this.delegate = parent; }Copy the code
BeanDefinitionParserDelegate used to parse the XML bean definitions of stateful delegate class. Use {@link BeanDefinitionParser BeanDefinitionParsers} or {@link BeanDefinitionDecorator for the main parser and any extension BeanDefinitionDecorators}.