General documentation: Article directory Github: github.com/black-ant

A. The preface

In the second IOC article, I still choose a soft spot. This one talks about the loading methods of Resource and Document, which is also relatively simple.

The system of scanning part includes Resource, Document, and Annotation, and I’ll just say the first two

2. Resource system

Resource is the foundation of everything. All external objects can be thought of as a Resource. For this reason, Spring provides many Resource implementation classes:

Common resources are used for the following functions:

// When different ResourceLoader are used to load resources, different resources are generated based on different Resource typesC-bytearrayresource: Resource implementation of a given byte array for loading content from any given byte array without resorting to the single-use InputStreamResource C-classpathResource: Resource implementation of the classpath resource, using the given ClassLoader or the given Class to load the resource C-ContextResource: Extension interface c-Descriptiveresource for loading the resource from the closed "context" : A simple resource implementation that holds a description of a resource but does not point to an actual readable resource c-EncodedResource: Combines the resource descriptor with a specific encoding or character set for reading from the resource Resource implementation handles a file system target c-FileurlResource: It assumes file parsing to the extent that it implements the WritableResource interface C-importresource: Indicates one or more resources that contain the definition of the bean to be imported c-InputStreamResource: Given the resource implementation of InputStream, use c-ServletContextResource only if no other specific resource implementation is applicable: C- VfsResource: a JBoss VFS based resource implementation C- WritableResource: an extended interface of the resource that supports writing to the resource. Provides an output stream accessorCopy the code

Resource System functions:

// The core class for Unified Resources is: Resource, which is an abstraction and access interface for all resources of the Spring frameworkI-resource e-inputStreamSource c-AbstractResource i-resource > I-Resource e-inputStreamSource c-AbstractResource i-resource > All resources in Spring can be represented by Resource: AbstractResource inherits from Resource, There are many common functions in Resource: exists/isReadable/isOpen/isFile/getURL/getFile/readableChannel contentLength / LastModified/createRelative/getFileName/getDescription > AbstractResource The encapsulation of resources of type java.io.File, as long as you are working with files, you can basically work with FileSystemResource as well - supporting both files and urls, implementing the WritableResource interface, From the Spring Framework5.0In the beginning, FileSystemResource uses the NIO2 API for read/write interaction. - ByteArrayResource: encapsulates data provided by byte arrays. - URIResource: encapsulates java.net.URL resources. The URL is internally delegated for specific resource operations. - ClassPathResource :class pathType resource implementation. Use the givenClassLoaderOr givenClassTo load resources. -InputStreamResource: will be givenInputStreamAs a resourceResourceImplementation class of.C- AbstractResource
    - exists() : determines whether the file existsCopy the code

Resource interface


C- AbstractResource 
    TODO
    

Copy the code

Resources are loaded through ResourceLoader. An important ResourceLoader has the following structure:

Note that ApplicationContext is basically a ResourceLoader implementation class, so they usually carry ResourceLoader functionality

ResourceLoader Loading system

C11- ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader: ResourceLoader Return a Resource instance based on the location of the provided Resource - support URL location Resource/ClassPath location Resource/relative path Resource m-getClassLoader () : Return ClassLoader instance Mc-resourceloader (ClassLoader) -thread.currentThread ().getContextClassLoader() - ClassUtils.getDefaultClassLoader() - setClassLoader() :interface ResourcePatternResolver extends ResourceLoader
    
C18- DefaultResourceLoader
    MC- DefaultResourceLoader
        - ClassUtils.getDefaultClassLoader(a);
    MC- DefaultResourceLoader(@NullableClassLoader classLoader) M- addProtocolResolver(ProtocolResolver) : M- getResource(String location) - first, load Resource(String location), return Resource(String location) - second, start with /, Call the #getResourceByPath() method to return a resource of type ClassPathContextResource - again, with classpath: First, return a resource of type ClassPathResource - get the current ClassLoader by #getClassLoader() - and then, depending on whether it is a file URL or not, return a resource of type FileUrlResource. Otherwise, return a resource of type UrlResource - and finally, a resource of type ClassPathContextResource// resourceLoader.getResource("D:/Users/chenming673/Documents/spark.txt");C-resourcepatternresolver: Default implementation of ResourceLoader m-setClassLoader/getClassLoader > FileSystemResourceLoader Internal class: FileSystemContextResource extends FileSystemResource C - ProtocolResolver: user-defined protocol resources strategy? - SPI as DefaultResourceLoader: it allows users to customize resource loading protocols without having to subclass ResourceLoader? M- Resolve (String, ResourceLoader) M- Resolve (String, ResourceLoader)Copy the code

The main class involved in a Resource loading process

// Let's look at the definitionReader element again
C160- AbstractBeanDefinitionReader
	M- loadBeanDefinitions(location, null) 
	M- loadBeanDefinitions(String location, @NullableSet<Resource> actualResources) -getResourceloader Obtains a ResourceLoader. - ResourceLoader obtains Resource from location [] -> - Add Resource to actualResources, Used to deal with the rear C16 ResourcePatternResolver C51 - GenericApplicationContext M51_033 - getResources (String locationPattern) C17 - PathMatchingResourcePatternResolver M17_02- getResources(String locationPattern) - classpath*: At the beginning, Respectively called findPathMatchingResources (- >)/findAllClassPathResources - getResourceLoader () call to obtain the Resource - > M18_05 M17_03 - FindPathMatchingResources - access path, recursive package path - through package URLResource call doFindPathMatchingFileResources M17_04 - access to class FindAllClassPathResources - call doFindAllClassPathResources get classResource M17_05 - doFindAllClassPathResources - get a ClassLoader, get resource URL from ClassLoader - Convert url list to UrlResource by convertClassLoaderURL? - this is actually the package path -> PS:M17_05_01// PS:M17_05_01 
file:/D:/java/workspace/git/case/case%20Origin%20Source/case%20SpringBootIOC/target/classes/com/gang/study/source/springboot/demo/ C18- DefaultResourceLoader M18_05- GetResource (String location) - If there is a collection of ProtocolResolvers, loop through the collection and attempt to handle a ProtocolResolver. Generates a ClassPathContextResource - if classpath begins,newCreate a ClassPathResource and configure a ClassLoader for it? So, here bean.xml is mapped to a ClassPathResource - or, if it's a URL type, a FileUrlResource// M17_03 pseudo-code
// locationPattern -- classpath*:com/gang/study/source/springboot/demo/**/*.class
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    // classpath*:com/gang/study/source/springboot/demo/
    String rootDirPath = determineRootDir(locationPattern);
    // **/*.class
    String subPattern = locationPattern.substring(rootDirPath.length());
    
    // Scan the path and convert the resources in the path to the Resource array
    Resource[] rootDirResources = getResources(rootDirPath);
    Set<Resource> result = new LinkedHashSet<>(16);
    for (Resource rootDirResource : rootDirResources) {
        rootDirResource = resolveRootDirResource(rootDirResource);
        URL rootDirUrl = rootDirResource.getURL();
        if(equinoxResolveMethod ! =null && rootDirUrl.getProtocol().startsWith("bundle")) {
            URL resolvedUrl = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirUrl);
            if(resolvedUrl ! =null) {
                rootDirUrl = resolvedUrl;
            }
            rootDirResource = new UrlResource(rootDirUrl);
        }
        if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            // Specifies the VFS loading mode
            result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
        }else if (ResourceUtils.isJarURL(rootDirUrl) || isJarResource(rootDirResource)) {
            // Load the JAR package path
            result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirUrl, subPattern));
        }else {
            / / load the classesresult.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern)); }}return result.toArray(new Resource[0]);
}
            

Copy the code

There are several scenarios in which resources are loaded, usually identified by location

Type 1: the classpath * : com/gang/study/source/springboot/demo / / *. * * class

/ / this path, its source for ComponentScanAnnotationParser to begin, the source of the earlier is the relevant scan logic ConfigurationC153- ComponentScanAnnotationParser M153_01- parse : By scanning the method dealing with ComponentScan - > M155_03 C155 - ClassPathBeanDefinitionScanner M155_03 - doScan (String... basePackages) -> M201_03 C201- ClassPathScanningCandidateComponentProvider M201_03- scanCandidateComponents(String BasePackage) - build an address -> PS:201 _03_01- call ResourcePatternResolver (AnnotationConfigServletWebServerApplicationContext) for Resouce - eventually call M17_02 C17 - PathMatchingResourcePatternResolver M17_02 - getResources (String locationPattern) - Class prefix, Final call M17_03 M17_03 - findPathMatchingResources M17_04 - findAllClassPathResources// M201_03 pseudo-code
private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
       / /...
    	String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        	resolveBasePackage(basePackage) + '/' + this.resourcePattern;
       // PS:201_03_01
       / / com. Gang. Study. Source. Springboot. Demo into
       // classpath*:com/gang/study/source/springboot/demo/**/*.class
    	Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
        / /...
        
            
}


Copy the code

Preload resources:

SequenceDiagram M153_01->>M155_03: ComponentScan M155_03->>M201_03: doScan M201_03->>M17_02: Call PathMatchingResourcePatternResolver < br > access to the resource

Resource Load of resources:

  • M17_02 : getResources
  • M17_03 : findPathMatchingResources
  • M17_04 : findAllClassPathResources
  • M17_05 : doFindAllClassPathResources
SequenceDiagram M17_02 - > > M17_03: found is for matching the classpath resource < br > call findPathMatchingResources M17_03 - > > M17_03: M17_02-->> M17_02-->>M17_04 Found for the classPath < br > call findAllClassPathResources M17_04 - > > M17_03: returns to the specific of the classPath or URLReource (actual) M17_03 - > > M17_05: Call ClassLoader to scan for the specific class object M17_05->>M17_03: return the object and put it into the collection

The core logic is:

  • If the path is for matching: findPathMatchingResources
  • Among them by matching, calls findAllClassPathResources the true path
  • Through the real path, call doFindAllClassPathResources for specific type of Resource

Type 2: CLASSPath *:messages.properties Resource loading

Preload resources:


/ / the load mainly comes from the Configuration of this kind of circumstance, such as MessageSourceAutoConfiguration
// To load the message resource, call ResourceBundle EditionC202 - ResourceBundleCondition M202_01 - getMatchOutcomeForBasename M202_02 getResources - through a constructed this one PathMatchingResourcePatternResolver - call getResources return related resource resources? - Here the mode is set because the resource needs to be specified// M202_02 pseudo-code
private Resource[] getResources(ClassLoader classLoader, String name) {
    String target = name.replace('. '.'/');
    return new PathMatchingResourcePatternResolver(classLoader).getResources("classpath*:" + target + ".properties");
			
}

/ / in the same way, call the PathMatchingResourcePatternResolver
/ / here without matching, direct call findAllClassPathResourcesC17 - PathMatchingResourcePatternResolver M17_02 - getResources (String locationPattern) - don't need to match, Direct call findAllClassPathResources - > M17_04 M17_04 - findAllClassPathResourcesCopy the code
SequenceDiagram M202_02->>M17_02: Classpath *:messages.properties M17_02->>M17_04: Don't need to match, the direct call findAllClassPathResources M17_04 - > > M17_02: returns the resource for URLResource M17_02 - > > M202_02: use resources Configuration

Type 3: RESOURCES of XML type

To the classpath: spring – common. XML, for example



/ / origin:loadBeanDefinitionsFromImportedResources(configClass.getImportedResources()); ? - Is caused by the ImportedResources annotation/ / process:C160- AbstractBeanDefinitionReader M- loadBeanDefinitions - ((ResourcePatternResolver) resourceLoader).getResources(location) ? - Notice that Resources is still the pring-common.xml object// Let's call XmlBeanDefinitionReader for further details
Copy the code

PS: As for the other is not representative, not detailed

3. Document system

When the unified resource is loaded, its XML type is processed as a Document object

Document scanning refers to scanning the Document system, which is mainly used to configure beans in XML mode

PS: In the early days, I also thought that XML Configuration was old and outdated, but now there is a different feeling, compared to the Configuration method, it is more organized, in fact, is not complex to use

Document system function

Let’s first look at the common method functions of Doument:

Document type objects, including.xml,.dto,.schemas, etc

Source: XmlBeanDefinitionReader#doLoadDocument(InputSource InputSource, Resource Resource

  • This method does two things
    • Call # getValidationModeForResource (the Resource the Resource) method, to obtain the specified Resource (XML) validation of the model
    • Call DocumentLoader#loadDocument to get the XML Document instance
C25- DocumentLoader : Strategy Document, by the interface org. Springframework. Beans. Factory. XML. DocumentLoader defined P - inputSource method parameters, Load the Document Resource. P-entityresolver method parameter, the parser that parses the file. The p-errorHandler method argument, which handles errors during loading the Document object. P- validationMode method parameter, validationMode. P-namespaceaware method parameter, namespace supported. If you want to provide support for XML namespaces, you need a value oftrue. C26 - DefaultDocumentLoader: the default implementation class DocumentLoader M26_01 loadDocument - first, call # createDocumentBuilderFactory (...). Method, create javax.mail. XML. Parsers. DocumentBuilderFactory object - DocumentBuilderFactory. NewInstance (); - create DocumentBuilderFactory - factory. SetNamespaceAware (namespaceAware); Set namespace support -- call the #createDocumentBuilder method, . Create javax.mail. XML parsers. DocumentBuilder objects to create DocumentBuilder object - set EntityResolver properties - set ErrorHandler properties - call DocumentBuilder#parse(InputSource) method. Parse the InputSource and return the Document object// XmlBeanDefinitionReader :     M-getentityresolver () : returns the specified resolver or, if not specified, constructs an unspecified default resolver -1 ResourceLoader resourceLoader = getResourceLoader();
        IF-2resourceLoader ! =null 
            - this.entityResolver = new ResourceEntityResolver(resourceLoader);
        ELSE-2 
            - this.entityResolver = new DelegatingEntityResolver(getBeanClassLoader());

Copy the code

Document scan tracking:


// Starting point: The starting point of Document is, where the XML is converted to Document by loading the XML from a Resource
C- ConfigurationClassBeanDefinitionReader
    M- loadBeanDefinitionsFromImportedResources 

// If you want to do this, please write the following definitionReader element: XmlBeanDefinitionReaderC21- XmlBeanDefinitionReader M21_01- doLoadBeanDefinitions(InputSource inputSource, - registerBeanDefinitions(doc, registerBeanDefinitions) - registerBeanDefinitions(doc, registerBeanDefinitions) The resource) registered Bean M21_02 - doLoadDocument - documentLoader. LoadDocument: C- DocumentLoader C23- DefaultDocumentLoader i-DocumentLoader M23_01- loadDocument(InputSource InputSource, EntityResolver entityResolver,ErrorHandler errorHandler,int validationMode, booleanNamespaceAware) - create a DocumentBuilderFactory createDocumentBuilderFactory - > M23_02 - create a through DocumentBuilderFactory DocumentBuilder - > M23_03 - DocumentBuilder parse method interpretation Document M23_02 - createDocumentBuilderFactory (int validationMode, booleanNamespaceAware) - Generate a DocumentBuilderFactory as a result of a newInstance - Set namespaceAware, Validating, And the Attribute? M23_03 -createDocumentBuilder (DocumentBuilderFactory Factory, EntityResolver entityResolver, ErrorHandler ErrorHandler) - Generates the DocumentBuilder from the factory passed in - sets EntityResolver and ErrorHandler for the DocumentBuilder/ / M23_01 added
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
            ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
    DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
    DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
    return builder.parse(inputSource);
}


/ / M23_02 added
protected DocumentBuilderFactory createDocumentBuilderFactory(int validationMode, boolean namespaceAware){
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setNamespaceAware(namespaceAware);
    if(validationMode ! = XmlValidationModeDetector.VALIDATION_NONE) { factory.setValidating(true);
        if (validationMode == XmlValidationModeDetector.VALIDATION_XSD) {
            factory.setNamespaceAware(true);
            factory.setAttribute(SCHEMA_LANGUAGE_ATTRIBUTE, XSD_SCHEMA_LANGUAGE);
            / /... Omit the catch}}return factory;
}


// N23_03
protected DocumentBuilder createDocumentBuilder(DocumentBuilderFactory factory,
            @Nullable EntityResolver entityResolver, @Nullable ErrorHandler errorHandler)
            throws ParserConfigurationException {

        DocumentBuilder docBuilder = factory.newDocumentBuilder();
        if(entityResolver ! =null) {
            docBuilder.setEntityResolver(entityResolver);
        }
        if(errorHandler ! =null) {
            docBuilder.setErrorHandler(errorHandler);
        }
        return docBuilder;
}  
    

Copy the code

DocumentBuilder

DocumentBuilder is an abstract class whose main implementation is DocumentBuilderImpl C24-DocumentBuilder f-DomParser DOMParser; F- EntityResolver fInitEntityResolver F- ErrorHandler fInitErrorHandler MC- DocumentBuilderImpl M24_01- parse - Domparser.parse (is) -domParser getDocument Gets the Document/ / here involves com.sun.org.apache.xerces.internal.parsers.DOMParser objectC- DOMParser ? - Used for DOM type parsingCopy the code

Complete Document processing flowchart

// Step 1 : ConfigurationClassBeanDefinitionReader # loadBeanDefinitions? - For loadingclassThe class of the aboveclasspath load
// Step2:AbstractBeanDefinitionReader # loadBeanDefinitions? - Start loadingxmlFile / /Step3:XmlBeanDefinitionReader # loadBeanDefinitions? - Handles the loadingresourceObject,xml resourceYou can see the loading of // aboveStep4: The main processing process beginsC21- XmlBeanDefinitionReader
    M21_01- doLoadBeanDefinitions
        - doLoadDocument(inputSource.resource) - >M21_02
    M21_02- doLoadDocument
    
    
C26- DefaultDocumentLoader : DocumentLoaderThe default implementation class forM26_01- loadDocument
    
C24- DocumentBuilder
      M24_01- parse


Copy the code
SequenceDiagram M21_01->>M21_01: Load the bean.xml file and obtain the resource file M21_01->>M21_02: DoLoadDocument handles resource object M21_02-->>M26_01: DocumentBuilderFactory -> DocumentBuilder<br> DocumentBuilder<br> DocumentBuilder<br> DocumentBuilder<br> Return Document object M21_02-->>M21_01: handles Document object -> registerBeanDefinitions

Extend the EntityResolver object

The EntityResolver object is used to parse a Document.

Refer to @cmsblogs.com/?p=2695

  • ResourceEntityResolver: Inherits from EntityResolver and resolves entity references using ResourceLoader.
  • DelegatingEntityResolver: Implementation of EntityResolver, which represents BeansDtdResolver and PluggableSchemaResolver in XML schemas.
  • BeansDtdResolver: Spring Bean DTD parser. An implementation of EntityResolver to load a DTD from a CLASspath or JAR file.
  • PluggableSchemaResolver: Resolves the Schema URL to the local CLASspath resource using a series of Map files
protected EntityResolver getEntityResolver(a) {
    if (this.entityResolver == null) {
        ResourceLoader resourceLoader = getResourceLoader();
        if(resourceLoader ! =null) {
            this.entityResolver = new ResourceEntityResolver(resourceLoader);
        }else {
            this.entityResolver = newDelegatingEntityResolver(getBeanClassLoader()); }}return this.entityResolver;
}

Copy the code

Supplementary Document function

Document is all about interpreting XML as readable objects

Supplement the DTD and XSD

Refer to the @cmsblogs.com/?p=2688 documentation. I suggest you look at the original version. Here are some key points

Document Type Definition (DTD) is a validation mechanism for XML files and is a part of XML files.

A DTD is an effective validation to ensure that an XML document is properly formatted. It defines the elements, attributes, arrangement, content types of elements, and element hierarchy of the relevant XML document. In fact, A DTD is the “vocabulary” and “syntax” of XML. We can compare an XML file with a DTD file to see whether the document conforms to the specification and whether the elements and tags are used correctly. To use a DTD in Spring, declare in the Spring XML file header:

<? xml version="1.0" encoding="UTF-8"? > <! DOCTYPE beans PUBLIC"-//SPRING//DTD BEAN//EN"  "http://www.springframework.org/dtd/spring-beans.dtd">

Copy the code

DTDS have been a driving force for XML for a while, but they have some drawbacks of their own:

  • Instead of using XML, it defines its own format, which is less reusable than parsers;
  • There is no standard programming interface for building and accessing DTDS, making it difficult for parsers to simply parse DTD documents.
  • DTDS are less restrictive on the types of elements; At the same time other constraints are called weak.
  • DTDS are less extensible.
  • DTD documents based on regular expressions have limited descriptive capabilities.

XSD has the following advantages To address the shortcomings of DTDS, the W3C introduced XSD in 2001. XML Schemas Definition (XSD) is the XML Schema language. An XML Schema is itself an XML document and uses XML syntax, so it is easy to parse XSD documents.

  • XML Schema is based on XML and has no specific syntax
  • XML Schemas can be parsed and processed just like any other XML file
  • XML Schema provides a richer variety of data types than DTDS.
  • XML Schema provides an extensible data model.
  • XML Schema supports comprehensive namespaces
  • XML Schema supports attribute groups.

Different validation modes are resolved using different parsers:

  • XSD: www.springframework.org/schema/bean…
  • DTD: www.springframework.org/dtd/spring-…

ValidationMode validation location


C21- XmlBeanDefinitionReader
    M21_02- doLoadDocument -> PS:M21_02_01
    
// PS:M21_02_01 specifies the ValidationMode
return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,getValidationModeForResource(resource), isNamespaceAware());


protected int getValidationModeForResource(Resource resource) {
    int validationModeToUse = getValidationMode();
    if(validationModeToUse ! = VALIDATION_AUTO) {return validationModeToUse;
    }
    int detectedMode = detectValidationMode(resource);
    if(detectedMode ! = VALIDATION_AUTO) {return detectedMode;
    }
    return VALIDATION_XSD;
}


/ / constant
/**
* Indicates that the validation mode should be auto-guessed, since we cannot find
* a clear indication (probably choked on some special characters, or the like).
*/
public static final int VALIDATION_AUTO = 1;

/**
* Indicates that DTD validation should be used (we found a "DOCTYPE" declaration).
*/
public static final int VALIDATION_DTD = 2;

/**
* Indicates that XSD validation should be used (found no "DOCTYPE" declaration).
*/
public static final int VALIDATION_XSD = 3;


Copy the code

conclusion

The scanning collection of Resource and Document is the basis of everything. When the collection of Resource and Document is complete, you can start to load related classes