• Web core – the Servlet
  • Spring source code series: Startup process
  • Spring source code series: Container refresh
  • Spring source series: BeanFactory creation
  • Spring source code series: BeanDefinition source code parsing
  • Spring source code series: BeanDefinition load (top)
  • Spring source code series: BeanDefinition load (middle)
  • Spring source code series: BeanDefinition load (below)

The last article is to comb the Bean resolution registration process, for some details did not study, such as element attribute value processing, constructor processing and so on. This article will learn to record the relevant points.

Let’s first look at where BeanDefinitiond is generated specifically. Here is the order of method requests.

    1. DefaultBeanDefinitionDocumentReader.parseDefaultElement
    1. DefaultBeanDefinitionDocumentReader.processBeanDefinition
    1. BeanDefinitionParserDelegate.parseBeanDefinitionElement

About elements of parsing the vast majority are in BeanDefinitionParserDelegate and its subclasses. OK, look at parseBeanDefinitionElement this method:

public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, BeanDefinition containingBean) {

	this.parseState.push(new BeanEntry(beanName));
	String className = null;
	// In this case, the class name of 
      
        is read and loaded into BeanDefinition without instantiation
      
	if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
		className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
	}

	try {
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}
		// Generate a BeanDefinition object
		AbstractBeanDefinition bd = createBeanDefinition(className, parent);
		// Parse the properties of the current bean
		parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
		// Set the description information
		bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
		// Parse the bean element information
		parseMetaElements(ele, bd);
		parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
		parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
		// Parse the bean's constructor Settings
		parseConstructorArgElements(ele, bd);
		// Parse property Settings
		parsePropertyElements(ele, bd);
		parseQualifierElements(ele, bd);

		bd.setResource(this.readerContext.getResource());
		bd.setSource(extractSource(ele));

		return bd;
	}
	// Exception 1: ClassNotFoundException
	catch (ClassNotFoundException ex) {
		error("Bean class [" + className + "] not found", ele, ex);
	}
	// Exception 2: NoClassDefFoundError
	catch (NoClassDefFoundError err) {
		error("Class that bean class [" + className + "] depends on not found", ele, err);
	}
	// Other unknown error
	catch (Throwable ex) {
		error("Unexpected failure during bean definition parsing", ele, ex);
	}
	finally {
		this.parseState.pop();
	}

	return null;
}

Copy the code

Here we use the parse property as an example to see the details:

// Parse the attribute child element of the given bean element.
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
    // Get the child element node
    NodeList nl = beanEle.getChildNodes();
    / / traverse
    for (int i = 0; i < nl.getLength(); i++) {
    	Node node = nl.item(i);
    	// Whether to include a property identifier
    	if(isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) { parsePropertyElement((Element) node, bd); }}}Copy the code

This is followed by executing the specific property, which is done in parsePropertyElement:

// Parse a property element.
public void parsePropertyElement(Element ele, BeanDefinition bd) {  
    // Get the property name first
	String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
	// Check if there is a name
	if(! StringUtils.hasLength(propertyName)) { error("Tag 'property' must have a 'name' attribute", ele);
		return;
	}
	this.parseState.push(new PropertyEntry(propertyName));
	try {
	   // Verify that a property of the same name exists in the same bean
		if (bd.getPropertyValues().contains(propertyName)) {
			error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
			return;
		}
		// Parse out the property value
		Object val = parsePropertyValue(ele, bd, propertyName);
		// Encapsulates the PropertyValue object
		PropertyValue pv = new PropertyValue(propertyName, val);
		parseMetaElements(ele, pv);
		pv.setSource(extractSource(ele));
		bd.getPropertyValues().addPropertyValue(pv);
	}
	finally {
		this.parseState.pop(); }}Copy the code

In parsePropertyValue, all property child elements are parsed concretely. We know that property contains set elements such as List, set, Map, prop, etc. in addition to single values. These are encapsulated into corresponding Managerd objects. For example, ManagedList. Different collection type pages also correspond to a parsing method, such as using parseListElement to parse a list. The parsing is done in BeanDefinitionParserDelegate class. This I would have taken a back to learn BeanDefinitionParserDelegate this class.

The loading process of beans is completed through layers of parsing. However, for the current Ioc container, only some data preparation work for Bean object management is completed, that is, the initialization work. The current BeanDefginiton contains some static configuration information, and the Bean instantiation has not been carried out. This instantiation is done at dependency injection time.