编程知识 cdmana.com

Spring5

XML

By reading the xml register bean

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean id="user" class="com.jame.pojo.User"/>
</beans>
public static void test1(){
		XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));
		Object o = factory.getBean("user");
		System.out.println(o);
	}

First of all to see XmlBeanFactory structure

diagram

XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("beans.xml"));

Creating XmlBeanFactory When you pass in a ClassPathResource object , Let's look at this object first

ClassPathResource

​ stay java Abstract different resources into URL, By registering different handler(URLStreamHandler) To handle the read logic of different resources , and URL There's no basic way , These are all Spring The internal use of resources to achieve their own abstract structure :Resource Interface to encapsulate the underlying resources

​ InputStreamSource Encapsulate anything that can be returned InputStream Class , such as File,ClassPath Resources and so on , It only defines one method :getInputStream(); This method returns a new InputStream object

​ Resource The interface abstracts all Spring The underlying resources used internally , First, it defines 3 A way to determine the current state of resources , Existence (exists), Readability (isReadable), Open or not (isOpen), in addition Resource Interfaces also provide different resources to URL URI File Conversion of type , And get lastModified attribute , file name ( Filename without path information ,getFilename()) Methods , Create a method to create relative resources based on the current path createRelative()

With Resource After the interface, the resource files can be processed uniformly

ClassPathResource

public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
    Assert.notNull(path, "Path must not be null");
    String pathToUse = StringUtils.cleanPath(path);
    if (pathToUse.startsWith("/")) {
        pathToUse = pathToUse.substring(1);
    }
    this.path = pathToUse;
    this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader());
}

When passed Resource After the related class finishes encapsulating the configuration file , Read the configuration file to XmlBeanDefinitionReader To deal with it

Next, let's move on to the construction method

XmlBeanFactory

public XmlBeanFactory(Resource resource) throws BeansException {
    // call XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) Construction method 
    this(resource, null);
}
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
    super(parentBeanFactory);
    // The entry point for loading resources 
    this.reader.loadBeanDefinitions(resource);
}

In the process of analysis xml Documents before , Have a look first super Method called

AbstractAutowireCapableBeanFactory

public AbstractAutowireCapableBeanFactory() {
    super();
    // Ignore the auto assembly function of a given interface 
    // Get... By default A, and A Of Bean There are also properties B, and B It's not initialized yet , that Spring Will B initialization ,
    // But in some cases it doesn't initialize B, for example B Inherited BeanFactoryAware Interface 
    ignoreDependencyInterface(BeanNameAware.class);
    ignoreDependencyInterface(BeanFactoryAware.class);
    ignoreDependencyInterface(BeanClassLoaderAware.class);
}

Now you can see this.reader.loadBeanDefinitions(resource); The method

The main process is as follows

  1. Encapsulate resource files Get into XmlBeanDefinitionReader After that, the parameters Resource Use EncodedResource Class to encapsulate
  2. Get input stream , from Resource Get the corresponding InputStream And construction InputSource
  3. By constructing InputSource Instance and Resource Instance continues to call function doLoadBeanDefinitions

XmlBeanDefinitionReader

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    return loadBeanDefinitions(new EncodedResource(resource));
}

EncodedResource It is used to process the encoding of resource files , The main logic is embodied in getReader() In the method , When the encoding is set Spring The corresponding code will be used as the input code

EncodedResource

public Reader getReader() throws IOException {
    if (this.charset != null) {
        return new InputStreamReader(this.resource.getInputStream(), this.charset);
    }
    else if (this.encoding != null) {
        return new InputStreamReader(this.resource.getInputStream(), this.encoding);
    }
    else {
        return new InputStreamReader(this.resource.getInputStream());
    }
}

When constructed encodedResource After the object , Once again loadBeanDefinitions(new EncodedResource(resource))

This method is the real data preparation stage

XmlBeanDefinitionReader

public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
    Assert.notNull(encodedResource, "EncodedResource must not be null");
    if (logger.isTraceEnabled()) {
        logger.trace("Loading XML bean definitions from " + encodedResource);
    }
    // Record the loaded resources by attributes 
    Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
    if (currentResources == null) {
        currentResources = new HashSet<>(4);
        this.resourcesCurrentlyBeingLoaded.set(currentResources);
    }
    if (!currentResources.add(encodedResource)) {
        throw new BeanDefinitionStoreException(
            "Detected cyclic loading of " + encodedResource + " - check your import definitions!");
    }
    try {
        // from encodedResource In order to get Resource object , And then from Resource In order to get InputStream object 
        InputStream inputStream = encodedResource.getResource().getInputStream();
        try {
            // This class doesn't come from Spring, The full path is org.xml.sax
            InputSource inputSource = new InputSource(inputStream);
            if (encodedResource.getEncoding() != null) {
                inputSource.setEncoding(encodedResource.getEncoding());
            }
            // The real core part =======================----
            return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            //=========================================
        }
        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();
        }
    }
}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
    throws BeanDefinitionStoreException {

    try {
        // adopt inputSource obtain Document object 
        Document doc = doLoadDocument(inputSource, resource);
        int count = registerBeanDefinitions(doc, resource);
        if (logger.isDebugEnabled()) {
            logger.debug("Loaded " + count + " bean definitions from " + resource);
        }
        return count;
    }
    // The rest is exception handling 

The code above actually does 3 thing

  1. Get right XML File validation mode
  2. load XML, And get the corresponding Document
  3. According to the returned Document register Bean Information

Let's start with the first thing : obtain xml File validation mode

Under the simple said DTD and XSD difference

DTD It's a kind of xml Constraint pattern language , One DTD Document contains : Definition rules of elements , Rules for defining the relationship between elements , Elements can use rules , Available entity or symbol rules

If you use it DTD Validation mode only needs to be in XML File header statement is OK

XML Schema Language is XSD It describes the xml Document structure , You can specify one xml schema To verify a xml,xml schema Is itself a xml file , You can use universal xml The parser parses it

In the use of xml schema The document is right xml Check the case file , In addition to declaring a namespace , You must also specify the... Corresponding to the namespace xml schema Document storage location , adopt schemaLocation Property to specify xml schema File location or URL Address

Reading of validation mode

XmlBeanDefinitionReader

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
    return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
                                            getValidationModeForResource(resource), isNamespaceAware());
}
protected int getValidationModeForResource(Resource resource) {
    int validationModeToUse = getValidationMode();
    // If the authentication mode is specified manually, the specified authentication mode is used 
    if (validationModeToUse != VALIDATION_AUTO) {
        return validationModeToUse;
    }
    int detectedMode = detectValidationMode(resource);
    // If not specified, automatic detection is used 
    if (detectedMode != VALIDATION_AUTO) {
        return detectedMode;
    }
    return VALIDATION_XSD;
}

detectValidationMode(resource); Automatic detection verification mode

protected int detectValidationMode(Resource resource) {
    if (resource.isOpen()) {
        throw new BeanDefinitionStoreException(
            "Passed-in Resource [" + resource + "] contains an open stream: " +
            "cannot determine validation mode automatically. Either pass in a Resource " +
            "that is able to create fresh streams, or explicitly specify the validationMode " +
            "on your XmlBeanDefinitionReader instance.");
    }

    InputStream inputStream;
    try {
        inputStream = resource.getInputStream();
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException(
            "Unable to determine validation mode for [" + resource + "]: cannot open InputStream. " +
            "Did you attempt to load directly from a SAX InputSource without specifying the " +
            "validationMode on your XmlBeanDefinitionReader instance?", ex);
    }

    try {
        // And to detectValidationMode To complete the verification 
        return this.validationModeDetector.detectValidationMode(inputStream);
    }
    catch (IOException ex) {
        throw new BeanDefinitionStoreException("Unable to determine validation mode for [" +
                                               resource + "]: an error occurred whilst reading from the InputStream.", ex);
    }
}

XmlValidationModeDetector

// The way to judge is whether it contains DOCTYPE, If it is included, it is DTD, Otherwise, it would be XSD
public int detectValidationMode(InputStream inputStream) throws IOException {
    // Peek into the file to look for DOCTYPE.
    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    try {
        boolean isDtdValidated = false;
        String content;
        while ((content = reader.readLine()) != null) {
            content = consumeCommentTokens(content);
            // If the read line is empty or the comment is omitted 
            if (this.inComment || !StringUtils.hasText(content)) {
                continue;
            }
            if (hasDoctype(content)) {
                isDtdValidated = true;
                break;
            }
            // If you read < Start symbol , The validation mode must be before the start symbol 
            if (hasOpeningTag(content)) {
                // End of meaningful data...
                break;
            }
        }
        return (isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD);
    }
    catch (CharConversionException ex) {
        // Choked on some character encoding...
        // Leave the decision up to the caller.
        return VALIDATION_AUTO;
    }
    finally {
        reader.close();
    }
}

obtain Document

It can be done by verification Document To load the , Also in XmlBeanFactoryReader No implementation in class , It's called loadDocument Method to implement

DocumentLoader I

Document loadDocument(
    InputSource inputSource, EntityResolver entityResolver,
    ErrorHandler errorHandler, int validationMode, boolean namespaceAware)
    throws Exception;

It's an interface , His implementation class is

DefaultDocumentLoader

// adopt SAX analysis XML file 
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
                             ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
	// establish DocumentBuilderFactory object 
    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    if (logger.isTraceEnabled()) {
        logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
    }
    // establish DocumentBuilder object 
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    // analysis inputSource To get Document object 
    return builder.parse(inputSource);
}

Let's mainly take a look at doLoadDocument Method passed in getEntityResolver() Parameters

XmlBeanDefinitionReader

protected EntityResolver getEntityResolver() {
    if (this.entityResolver == null) {
        // Determine default EntityResolver to use.
        ResourceLoader resourceLoader = getResourceLoader();
        if (resourceLoader != null) {
            this.entityResolver = new ResourceEntityResolver(resourceLoader);
        }
        else {
            this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());
        }
    }
    return this.entityResolver;
}

EntityResoulver usage

If SAX Applications need to implement custom processing of external entities , You have to implement this interface and use setEntutyResolver Method direction SAX Drive register an instance ,-- For resolving a XML,SAX First read this XML Declaration on document , Follow the statement to find the right DTD Definition , To validate the document , The default is to download the corresponding DTD Statement , and EntityResolver The role of the project itself is to provide a DTD Method declaration file , It's up to the program to find DTD Process of declaration , Such as DTD Put the files somewhere in the project , In the implementation, the document will be read directly back to SAX that will do , You don't have to go through the Internet to find the corresponding statement

EntityResolver Interface method declaration for

EntityResolver I

public abstract InputSource resolveEntity (String publicId,String systemId)

If the parsing validation mode is XSD The configuration file will read two parameters

publicId : null

systemId : xxxxxxxxxxx

The analytic verification mode is DTD Configuration file for

publicId : xxx

systemId : xxx

According to the previous Spring adopt getEntityResilver() Method pair EntityResolver Acquisition ,Spring Use in DelegatingEntityResolver Class is EntityResolver Implementation class of ,resolverEntity The implementation method is as follows

DelegatingEntityResolver

public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId)
    throws SAXException, IOException {

    if (systemId != null) {
        if (systemId.endsWith(DTD_SUFFIX)) {
            // If it is dtd Here's how it works 
            return this.dtdResolver.resolveEntity(publicId, systemId);
        }
        else if (systemId.endsWith(XSD_SUFFIX)) {
            // adopt META-INF/Spring.schemas analysis 
            return this.schemaResolver.resolveEntity(publicId, systemId);
        }
    }

    // Fall back to the parser's default behavior.
    return null;
}

Directly intercept the suffix to determine which parsing type it is

If it is DTD, Will go to the current path to find , If it is XSD, The default is to META-INF/Spring.schemas Find the corresponding in the file systemid Of XSD File and load

BeansDtdResolver

public InputSource resolveEntity(@Nullable String publicId, @Nullable String systemId) throws IOException {
    if (logger.isTraceEnabled()) {
        logger.trace("Trying to resolve XML entity with public ID [" + publicId +
                     "] and system ID [" + systemId + "]");
    }

    if (systemId != null && systemId.endsWith(DTD_EXTENSION)) {
        int lastPathSeparator = systemId.lastIndexOf('/');
        int dtdNameStart = systemId.indexOf(DTD_NAME, lastPathSeparator);
        if (dtdNameStart != -1) {
            String dtdFile = DTD_NAME + DTD_EXTENSION;
            if (logger.isTraceEnabled()) {
                logger.trace("Trying to locate [" + dtdFile + "] in Spring jar on classpath");
            }
            try {
                Resource resource = new ClassPathResource(dtdFile, getClass());
                InputSource source = new InputSource(resource.getInputStream());
                source.setPublicId(publicId);
                source.setSystemId(systemId);
                if (logger.isTraceEnabled()) {
                    logger.trace("Found beans DTD [" + systemId + "] in classpath: " + dtdFile);
                }
                return source;
            }
            catch (FileNotFoundException ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Could not resolve beans DTD [" + systemId + "]: not found in classpath", ex);
                }
            }
        }
    }

    // Fall back to the parser's default behavior.
    return null;
}

Parsing and registration BeanDefinitions

XmlBeanDefinitionReader

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
    // Use DefaultBeanDefinitionDocument Instantiation BeanDefinitionDocumentReader
    BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
    // Before recording statistics BeanDefinition Number of loads for 
    int countBefore = getRegistry().getBeanDefinitionCount();
    // Load and register bean
    documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
    // Record the BeanDefinition Number 
    return getRegistry().getBeanDefinitionCount() - countBefore;
}

Get into registerBeanDefinitions Method

DefaultBeanDefinitionDocumentReader

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
    this.readerContext = readerContext;
    // extract DocumentElement
    doRegisterBeanDefinitions(doc.getDocumentElement());
}
protected void doRegisterBeanDefinitions(Element root) {
    BeanDefinitionParserDelegate parent = this.delegate;
    this.delegate = createDelegate(getReaderContext(), root, parent);

    if (this.delegate.isDefaultNamespace(root)) {
        // Handle profile attribute 
        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)) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Skipped XML bean definition file due to specified profiles [" 							+ profileSpec +
                                 "] not matching: " + getReaderContext().getResource());
                }
                return;
            }
        }
    }
    // Parse before processing , It's left for subclasses to implement 
    preProcessXml(root);
    parseBeanDefinitions(root, this.delegate);
    // After processing, parse , It's left for subclasses to implement 
    postProcessXml(root);

    this.delegate = parent;
}

First, the program will go back beans Whether the node defines profile attribute , If it is defined, you will need to go to the environment variable to find , So the first assertion here is environment It can't be empty , because profile You can specify more than one at the same time , You need a program to split it , And parse each profile All of them conform to the definition of environment variables , If you don't define it, you don't waste performance parsing .

Parse and register BeanDefinition

DefaultBeanDefinitionDocumentReader

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
    // Yes bean To deal with 
    if (delegate.isDefaultNamespace(root)) {
        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)) {
                    // Handling of default labels 
                    parseDefaultElement(ele, delegate);
                }
                else {
                    // Yes bean To deal with 
                    delegate.parseCustomElement(ele);
                }
            }
        }
    }
    else {
        delegate.parseCustomElement(root);
    }
}
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
    //import Label handling 
    if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
        importBeanDefinitionResource(ele);
    }
    //alias Label handling 
    else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
        processAliasRegistration(ele);
    }
    //bean Label handling 
    else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
        processBeanDefinition(ele, delegate);
    }
    //beans Label handling 
    else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
        // recurse
        doRegisterBeanDefinitions(ele);
    }
}

First from bean Tags start

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
    BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
    if (bdHolder != null) {
        bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
        try {
            // Register the final decorated instance.
            BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
        }
        catch (BeanDefinitionStoreException ex) {
            getReaderContext().error("Failed to register bean definition with name '" +
                                     bdHolder.getBeanName() + "'", ele, ex);
        }
        // Send registration event.
        getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
    }
}

(1) First entrust BeanDefinitionDelegate Class parseBeanDefinitionElement Methods to analyze the elements , return BeanDefinitionHolder Instance of type bdHolder, After this method , bdHolder The instance already contains various properties configured in our configuration file , for example class, name,id, alias Something like that .

(2) When returned bdHolder If it is not empty, if there are custom attributes under the child node of the default label , You also need to parse the custom tags again .

(3) After parsing , Need to analyze the bdHolder To register , Again , The registration operation is delegated to BeanDefinitionReaderUtils Of registerBeanDefinition Method .

(4) Finally, a response event , Notify the listener you want to turn off , This bean It's loaded .

BeanDefinitionParserDelegate

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
    // analysis id attribute 
    String id = ele.getAttribute(ID_ATTRIBUTE);
    // analysis name attribute 
    String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

    // Division name attribute 
    List<String> aliases = new ArrayList<>();
    if (StringUtils.hasLength(nameAttr)) {
        String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
        aliases.addAll(Arrays.asList(nameArr));
    }

    String beanName = id;
    if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
        beanName = aliases.remove(0);
        if (logger.isTraceEnabled()) {
            logger.trace("No XML 'id' specified - using '" + beanName +
                         "' as bean name and " + aliases + " as aliases");
        }
    }

    if (containingBean == null) {
        checkNameUniqueness(beanName, aliases, ele);
    }
    // Further analysis 
    AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
    if (beanDefinition != null) {
        if (!StringUtils.hasText(beanName)) {
            try {
                // If it doesn't exist beanname	 So according to spring The naming rules generate the corresponding beanname
                if (containingBean != null) {
                    beanName = BeanDefinitionReaderUtils.generateBeanName(
                        beanDefinition, this.readerContext.getRegistry(), true);
                }
                else {
                    beanName = this.readerContext.generateBeanName(beanDefinition);
                    // Register an alias for the plain bean class name, if still possible,
                    // if the generator returned the class name plus a suffix.
                    // This is expected for Spring 1.2/2.0 backwards compatibility.
                    String beanClassName = beanDefinition.getBeanClassName();
                    if (beanClassName != null &&
                        beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                        !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                        aliases.add(beanClassName);
                    }
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("Neither XML 'id' nor 'name' specified - " +
                                 "using generated bean name [" + beanName + "]");
                }
            }
            catch (Exception ex) {
                error(ex.getMessage(), ele);
                return null;
            }
        }
        String[] aliasesArray = StringUtils.toStringArray(aliases);
        return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
    }

    return null;
}

(1) Extract... From the elements id as well as name attribute .

(2) All other attributes are further resolved and encapsulated to GenericBeanDefinition In an example of type .

(3) If detected bean Is not specified beanName, Then use the default rule for Bean Generate beanName

(4) Encapsulate the acquired information into BeanDefinitionHolder In the .

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

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		// analysis Class attribute 
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}
		String parent = null;
		// analysis parent attribute 
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			// Create for hosting AbstractBeanDefinition Type of GenericBeanDefinition
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);
			// Parse default bean Properties of 
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));


			// Parsing metadata 
			parseMetaElements(ele, bd);
			// analysis lookup-method	 attribute 
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			// analysis replace-method attribute 
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
			// Parse constructor parameters 
			parseConstructorArgElements(ele, bd);
			// analysis property Subelement 
			parsePropertyElements(ele, bd);
			// analysis qualifier Subelement 
			parseQualifierElements(ele, bd);

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

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

		return null;
	}

Create... For property hosting BeanDefinitionBeanDefinition It's an interface , stay Spring There are three kinds of implementation : RootBeanDefinition,ChildBeanDefinition as well as GenericBeanDefinition. All three implementations inherit AbstractBeanDefiniton , among BeanDefinition It's a configuration file The internal representation of the element label in the container . The element tag has class, scope, lazy-init And so on , BeanDefinition The corresponding beanClass, scope, lazylnit attribute , BeanDefinition and The attributes in are one-to-one . among RootBeanDefinition Is the most commonly used implementation class , It corresponds to the general The element tag , GenericBeanDefinition Is from 2.5 A new version of bean File configuration property definition class , It's a one-stop service class . The parent can be defined in the configuration file Hezi , Father use RootBeanDefinition Express , And son use ChildBeanDefiniton Express , And no father Of Just use RootBeanDefinition Express .AbstractBeanDefinition Abstract the common class information of the two Spring adopt BeanDefinition In the configuration file The configuration information is converted to the internal representation of the container , And these BeanDefiniton Sign up to BeanDefinitonRegistry in .Spring Container of BeanDefinitionRegistry like Spring Memory database for configuration information , mainly map Form preservation of , Follow up operations directly from BeanDefinitionRegistry Read configuration information in .

BeanDefinition

BeanDefinitionParserDelegate

protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName)
    throws ClassNotFoundException {

    return BeanDefinitionReaderUtils.createBeanDefinition(
        parentName, className, this.readerContext.getBeanClassLoader());
}
//=====================
public static AbstractBeanDefinition createBeanDefinition(
    @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException {

    GenericBeanDefinition bd = new GenericBeanDefinition();
    //parentName May is empty 
    bd.setParentName(parentName);
    if (className != null) {
        if (classLoader != null) {
            // If classLoader Not empty , Then we pass in the used classLoader The same virtual machine loads class objects , Otherwise, it's just a record classname
            bd.setBeanClass(ClassUtils.forName(className, classLoader));
        }
        else {
            bd.setBeanClassName(className);
        }
    }
    return bd;
}

When we create bean After the information bearing instance , Then it can be carried out bean The various properties of information resolve ,parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

版权声明
本文为[sunankang]所创,转载请带上原文链接,感谢
https://cdmana.com/2020/12/20201224173331246D.html

Tags spring
Scroll to Top