Reference article: [Spring 12/43] - IOC parsing bean Tags: parsing custom tags
https://www.cmsblogs.com/article/1391375348356222976
text
The previous four articles analyze the parsing process of Bean default tags, including basic properties The six sub elements (method, lookup method, replaced method, constructor Arg, property and qualifier) involve a lot of content and are divided into four articles. As a result, we have forgotten where to start and don't forget the original intention. processBeanDefinition() is responsible for the parsing of Bean tags. In the parsing process, we first call beandefinitionparserdelegate Parsebeandefinitionelement() completes the resolution of the default tag. If the resolution is successful (the returned bdholder! = null), first call BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired() to complete the resolution of the user-defined tag element. The previous four articles have analyzed the resolution of the default tag, so this article analyzes the resolution of the user-defined tag.
public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder definitionHolder) { return decorateBeanDefinitionIfRequired(ele, definitionHolder, null); }
Call decorateBeanDefinitionIfRequired():
public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder definitionHolder, @Nullable BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = definitionHolder; // Traverse the node to see if there are attributes suitable for decoration NamedNodeMap attributes = ele.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node node = attributes.item(i); finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } // Traverse the child nodes to see if there are child elements suitable for decoration NodeList children = ele.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition; }
Traverse the node (child node) and call decorateIfRequired() to decorate the node (child node).
public BeanDefinitionHolder decorateIfRequired( Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { // Gets the namespace of the custom tag String namespaceUri = getNamespaceURI(node); // Filter out default named labels if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { // Get the corresponding processor NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); if (handler != null) { // Decoration treatment BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); if (decorated != null) { return decorated; } } else if (namespaceUri.startsWith("http://www.springframework.org/")) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); } else { if (logger.isDebugEnabled()) { logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); } } } return originalDef; }
First, get the namespace of the custom tag. If it is not the default namespace, the corresponding processor will be acquired according to the namespace. Finally, the decorate() of the processor is invoked for decorating. The specific decoration process will not be described here, but will be described in detail later when analyzing custom labels. So far, the bean parsing process has been completed. Let's make a brief summary. The entry for parsing BeanDefinition is in defaultbeandefinitiondocumentreader parseBeanDefinitions() . This method will judge whether the label is a default label or a user-defined label according to the command space. The default label is implemented by parseDefaultElement() and the user-defined label is implemented by parseCustomElement(). In the default label resolution, import, alias, bean and beans are processed according to different label names. The bean label resolution is the core, which is implemented by the processBeanDefinition() method. processBeanDefinition() starts to enter the core work of parsing, which is divided into three steps:
- Resolve default label: beandefinitionparserdelegate parseBeanDefinitionElement()
- Resolve the custom tag under the default tag: beandefinitionparserdelegate decorateBeanDefinitionIfRequired()
- Register resolved BeanDefinition: beandefinitionreaderutils registerBeanDefinition
In the default label parsing process, the core work is implemented by the parseBeanDefinitionElement() method, which will parse the attributes and child elements of the Bean label in turn, and return a GenericBeanDefinition instance object after parsing.