[spring source code] beandefinitiondocumentreader parsing


Spring BeanDefinitionDocumentReader

  • Author: HuiFer
  • Source code reading warehouse:SourceHot-spring
  • Full path:org.springframework.beans.factory.xml.BeanDefinitionDocumentReader
 * SPI for parsing an XML document that contains Spring bean definitions. * Used by {@link XmlBeanDefinitionReader} for actually parsing a DOM document. * * <p>Instantiated per document to parse: implementations can hold * state in instance variables during the execution of the * {@code registerBeanDefinitions} method &mdash;  For example, global * settings that are defined for all bean definitions in the document</p>
 * @author Juergen Hoeller * @author Rob Harrop * @since 18.12.2003 * @see XmlBeanDefinitionReader#setDocumentReaderClass */public interface BeanDefinitionDocumentReader {
 /*** Read bean definitions from the given DOM document and * register them with the registry in the given reader context. * register bean definitions
 * @param doc the DOM document * @param readerContext the current context of the reader * (includes the target registry and the resource being parsed) * @throws BeanDefinitionStoreException in case of parsing errors */ void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) throws BeanDefinitionStoreException;
  • Through annotation, we can know that the behavior of this interface definition is as follows

    1. Read the XML configuration file and convert it into spring bean definition
    2. Put the spring bean definition into memory
    • Method function
    1. Read the given document, convert it into spring bean definition and put it into memory


  • Method of interface definition
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
 this.readerContext = readerContext; doRegisterBeanDefinitions(doc.getDocumentElement());}
  • Will eventually be handed over todoRegisterBeanDefinitionsimplement


@SuppressWarnings("deprecation")  // for Environment.acceptsProfiles(String...) protected void doRegisterBeanDefinitions(Element root) { // Any nested <beans> elements will cause recursion in this method. In // order to propagate and preserve <beans> default-* attributes correctly, // keep track of the current (parent)  delegate, which may be null. Create // the new (child) delegate with a reference to the parent for fallback purposes, // then ultimately reset this.delegate back to its original (parent) Reference. // this behavior emulates a stack of delegates without actually needing one. Beandefinitionparserdelegate parent = this. Delegate; // create beandefinitionparserdelegate this. Delegate = createdelete (getreadercontext(), root, parent);
 If (this. Delegate. Isdefaultnamespace (root)) {// get the profile attribute
 String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE); //  Whether there is profile if (stringutils. Hastext (profilespec)) {// data after profile segmentation
 String[] specifiedProfiles = StringUtils.tokenizeToStringArray( profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS); // We cannot use Profiles.of(...) since profile expressions are not supported // in XML config. See SPR-12458 for details. if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) { if (logger.isDebugEnabled()) { logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec + "] not matching: " + getReaderContext().getResource()); } return; } } }
 preProcessXml(root); //  Bean definition processing
 parseBeanDefinitions(root, this.delegate); //  Post XML processing
 this.delegate = parent; }
this.delegate = createDelegate(getReaderContext(), root, parent)
  • Parameter description

    1. XML parser
    2. Element XML node
    3. fatherBeanDefinitionParserDelegate
protected final XmlReaderContext getReaderContext() {
 Assert.state(this.readerContext != null, "No XmlReaderContext available"); return this.readerContext;}
  • Preprocessing method is null
  • Parse label

    1. Label import
    2. Label alias
    3. Tag bean
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
 If (delegate. Isdefaultnamespace (root)) {// child node list
 NodeList nl = root.getChildNodes();  For (int, I = 0; I < NL. Getlength(); I + +) {node node = NL. Item (I); if (node instanceof element) {element ele = (element) node; if (delegate. Isdefaultnamespace (ELE)) {// method of processing labels
 parseDefaultElement(ele, delegate); }  Else {// process custom tags
 delegate.parseCustomElement(ele); } } } }  Else {// process custom tags
 delegate.parseCustomElement(root); }}
  • Post processing method is null


  • takeparseDefaultElementPropose a complete analysis
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
 //Parse import tag
 If (delegate. Nodenameequals (ELE, import_element)) {importbeandefinitionresource (ELE);} // parse alias tag
 Else if (delegate. Nodenameequals (ELE, alias_element)) {processaliasregistration (ELE);} // resolve bean label
 Else if (delegate. Nodenameequals (ELE, bean_element)) {processbeandefinition (ELE, delegate);} // parse beans tag
 //Nested beans else if (delegate. Nodenameequals (ELE, nested_beans_element)) {// recursive doregisterbeandefinitions (ELE);}}


protected void importBeanDefinitionResource(Element ele) {
 //Get resource property
 String location = ele.getAttribute(RESOURCE_ATTRIBUTE); if (!StringUtils.hasText(location)) { getReaderContext().error("Resource location must not be empty", ele); return; }
 //Resolve system properties: e.g. "${user. Dir}" // handle configuration file placeholder
 location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);
 //Resource collection
 Set<Resource> actualResources = new LinkedHashSet<>(4);
 //Discover whether the location is an absolute or relative URI // is it an absolute address
 boolean absoluteLocation = false;  Try {// 1. Determine whether it is a URL // 2. Determine whether it is an absolute address by converting it to a URI
 absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); } catch (URISyntaxException ex) { // cannot convert to an URI, considering the location relative // unless it is the well-known Spring prefix "classpath*:" }
 // Absolute or relative?  If (absolutelocation) {try {// get the number of imports
 int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources);  if (logger.isTraceEnabled()) { logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]"); } } catch (BeanDefinitionStoreException ex) { getReaderContext().error( "Failed to import bean definitions from URL location [" + location + "]", ele, ex); } } else  {// no URL - > considering resource location as relative to the current file. Try {// number of imports
 int importCount; //  resource information 
 Resource relativeResource = getReaderContext().getResource().createRelative(location); //  Does the resource exist
 If (relativeresource. Exists()) {// determine the number of bean definitions loaded
 importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); //  Add resource collection
 actualResources.add(relativeResource); } //  There is no processing scheme for the resource
 Else {// get the data of the resource URL
 String baseLocation = getReaderContext().getResource().getURL().toString(); //  Get import quantity
 importCount = getReaderContext().getReader().loadBeanDefinitions( StringUtils.applyRelativePath(baseLocation, location), actualResources); }  if (logger.isTraceEnabled()) { logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]"); } } catch (IOException ex) { getReaderContext().error("Failed to resolve current resource location", ele, ex); } catch (BeanDefinitionStoreException ex) { getReaderContext().error(  "Failed to import bean definitions from relative location [" + location + "], ele, ex);}} resource [] actresarray = actualresources.toarray (new resource [0]); // wake up import to process events
 getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele));}


  • org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processAliasRegistration
  • Alias tag parsing
protected void processAliasRegistration(Element ele) {
 //Get name attribute
 String name = ele.getAttribute(NAME_ATTRIBUTE); //  Get alias attribute
 String alias = ele.getAttribute(ALIAS_ATTRIBUTE);  boolean valid = true; //  Name attribute validation
 If (! Stringutils. Hastext (name)) {getreadercontext(). Error ("name must not be empty", ELE); valid = false;} // alias property validation
 If (! Stringutils. Hastext (alias)) {getreadercontext(). Error ("alias must not be empty", ELE); valid = false;} if (valid) {try {getreadercontext(). Getregistry(). Registeraias (name, alias);} catch (exception Ex) {getreadercontext(). Error ("failed to register alias" "+ alias +" 'for bean with name "" + name + "", ele, ex);} // the event is triggered
 getReaderContext().fireAliasRegistered(name, alias, extractSource(ele)); }}


  • org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);  If (bdholder! = null) {// bean definition decoration
 bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);  Try {// register the final modified instance. // register beandefinition
 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); }  Catch (beandefinitionstoreexception Ex) {getreadercontext(). Error ("failed to register bean definition with name '" + bdholder. Getbeanname() + "'", ele, ex);} // send registration event. // the component registration event is triggered
 getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); }}


  • Create resource interface
protected static class ClassPathContextResource extends ClassPathResource implements ContextResource {
 public ClassPathContextResource(String path, @Nullable ClassLoader classLoader) { super(path, classLoader); }
 @Override public String getPathWithinContext() { return getPath(); }
 @Override public Resource createRelative(String relativePath) { String pathToUse = StringUtils.applyRelativePath(getPath(), relativePath); return new ClassPathContextResource(pathToUse, getClassLoader()); }}


 *Fire an import processed event. * * execute import event
 *@ param importedresource imported file
 *@ param actualresources resource path
 * @param source source */public void fireImportProcessed(String importedResource, Resource[] actualResources, @Nullable Object source) {
 this.eventListener.importProcessed(new ImportDefinition(importedResource, actualResources, source));}


event listeners

Methods of concern

void importProcessed(ImportDefinition importDefinition);


  • org.springframework.beans.testfixture.beans.CollectingReaderEventListener#importProcessed
public void importProcessed(ImportDefinition importDefinition) {

PutimportsIn the list
Focus method

void aliasRegistered(AliasDefinition aliasDefinition);```
- `org.springframework.beans.testfixture.beans.CollectingReaderEventListener#aliasRegistered`

public void aliasRegistered(AliasDefinition aliasDefinition) {
//Get the alias corresponding to the registered beanname
List<AliasDefinition> aliases = this.aliasMap.get(aliasDefinition.getBeanName()); If (aliases = = null) {aliases = new ArrayList < > (); / / beanname and alias correspondence settings
this.aliasMap.put(aliasDefinition.getBeanName(), aliases); } // Alias list add

Focus method

void componentRegistered(ComponentDefinition componentDefinition);

- `org.springframework.beans.testfixture.beans.CollectingReaderEventListener#componentRegistered`

public void componentRegistered(ComponentDefinition componentDefinition) {
this.componentDefinitions.put(componentDefinition.getName(), componentDefinition);}

Recommended Today

On the mutation mechanism of Clickhouse (with source code analysis)

Recently studied a bit of CH code.I found an interesting word, mutation.The word Google has the meaning of mutation, but more relevant articles translate this as “revision”. The previous article analyzed background_ pool_ Size parameter.This parameter is related to the background asynchronous worker pool merge.The asynchronous merge and mutation work in Clickhouse kernel is completed […]