This series of articles is my study Spring In the process of summing up , Which involves the relevant source code , May not be very friendly to readers , Please combine with my source code comments Spring Source code analysis GitHub Address To read

Spring edition :5.1.14.RELEASE

Before you start reading this series of articles , It is recommended to check it first 《 Deepen understanding Spring IoC( Interview questions )》 This article

For other articles in the series, check out :《 screwing Spring And IoC piece - Article reading guidance 》

BeanDefinition Loading phase of (XML file )

Last article 《Bean Of “ The predecessor ”》 Yes BeanDefinition Introduced ,Bean It's based on BeanDefinition Configuration meta information object generated . We are Spring We usually define a in these two ways Bean: Resources oriented (XML、Properties) Annotation oriented , that Spring How to translate the information defined in these two ways into BeanDefinition Object's , Next, we will analyze Resources oriented (XML、Properties) This way, Spring How is it handled

Get familiar with a piece of code :

dependency-lookup-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<!-- <context:component-scan base-package="org.geekbang.thinking.in.spring.ioc.overview" /> --> <bean id="user" class="org.geekbang.thinking.in.spring.ioc.overview.domain.User">
<property name="id" value="1"/>
<property name="name" value=" Little horse elder brother "/>
</bean>
</beans>
// establish BeanFactory Containers 
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
// XML The configuration file ClassPath route
String location = "classpath:/META-INF/dependency-lookup-context.xml";
// Load the configuration
int beanDefinitionsCount = reader.loadBeanDefinitions(location);
System.out.println("Bean Define the number of loads :" + beanDefinitionsCount);
// Dependency lookup
System.out.println(beanFactory.getBean("user"));;

This code is Spring The program uses IoC Containers , We can see IoC The process of using the container is as follows :

  1. establish BeanFactory object ( Bottom IoC Containers )
  2. establish BeanDefinitionReader object ( Resource resolver ), Related to chapter 1 Step created BeanFactory
  3. adopt BeanDefinitionReader load XML Profile resources , Parse out all of BeanDefinition object
  4. Do dependency lookup

The above first 3 The next step is to analyze Resource resources , take XML Defined in the file Bean It can be interpreted as BeanDefinition Configure meta information objects , Go together BeanDefinitionRegistry Registry registration , At this point, no corresponding Bean object , We need to get... Through dependency search Bean. Of course , We don't usually use this in real scenes Spring, All these jobs will have Spring To complete . Let's take a look at Sping How to load XML Of documents

BeanDefinitionReader Architecture

org.springframework.beans.factory.support.BeanDefinitionReader The class diagram of the interface is as follows :

The overview :

  • org.springframework.beans.factory.support.BeanDefinitionReader Interface ,BeanDefinition Reader

  • org.springframework.beans.factory.support.AbstractBeanDefinitionReader abstract class , Provides a common implementation , The specific resource loading logic is implemented by subclasses

  • org.springframework.beans.factory.xml.XmlBeanDefinitionReader,XML File resource parser , It is concluded that BeanDefinition Configure the meta information object and register

  • org.springframework.beans.factory.support.PropertiesBeanDefinitionReader,Properties File resource parser

BeanDefinitionReader Interface

org.springframework.beans.factory.support.BeanDefinitionReader Interface ,BeanDefinition Reader , The method of loading resources is defined , The code is as follows :

public interface BeanDefinitionReader {
/** return BeanDefinition Registry Center */
BeanDefinitionRegistry getRegistry(); /** return Resource Resource loader , The default is PathMatchingResourcePatternResolver */
@Nullable
ResourceLoader getResourceLoader(); /** Returns the class loader */
@Nullable
ClassLoader getBeanClassLoader(); /** return Bean Name generator for , The default is DefaultBeanNameGenerator */
BeanNameGenerator getBeanNameGenerator(); /** from Resource Resources BeanDefinition And return the quantity */
int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException; int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException; int loadBeanDefinitions(String location) throws BeanDefinitionStoreException; int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

AbstractBeanDefinitionReader abstract class

org.springframework.beans.factory.support.AbstractBeanDefinitionReader abstract class , Realized BeanDefinitionReader and EnvironmentCapable Interface , The code is as follows :

public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader, EnvironmentCapable {
private final BeanDefinitionRegistry registry;
@Nullable
private ResourceLoader resourceLoader; @Nullable
private ClassLoader beanClassLoader; private Environment environment; private BeanNameGenerator beanNameGenerator = new DefaultBeanNameGenerator(); protected AbstractBeanDefinitionReader(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
this.registry = registry; // Determine ResourceLoader to use.
if (this.registry instanceof ResourceLoader) {
this.resourceLoader = (ResourceLoader) this.registry;
}
else {
this.resourceLoader = new PathMatchingResourcePatternResolver();
} // Inherit Environment if possible
if (this.registry instanceof EnvironmentCapable) {
this.environment = ((EnvironmentCapable) this.registry).getEnvironment();
}
else {
this.environment = new StandardEnvironment();
}
} @Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
Assert.notNull(resources, "Resource array must not be null");
int count = 0;
for (Resource resource : resources) {
count += loadBeanDefinitions(resource);
}
return count;
} @Override
public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
return loadBeanDefinitions(location, null);
} public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
// get ResourceLoader object
ResourceLoader resourceLoader = getResourceLoader();
if (resourceLoader == null) {
throw new BeanDefinitionStoreException(
"Cannot load bean definitions from location [" + location + "]: no ResourceLoader available");
} if (resourceLoader instanceof ResourcePatternResolver) {
// Resource pattern matching available.
try {
// get Resource Array , because Pattern Pattern matching , There may be more than one Resource . For example, ,Ant Style location
Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
// load BeanDefinition People
int count = loadBeanDefinitions(resources);
if (actualResources != null) {
// Add to actualResources in
Collections.addAll(actualResources, resources);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location pattern [" + location + "]");
}
return count;
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"Could not resolve bean definition resource pattern [" + location + "]", ex);
}
}
else {
// Can only load single resources by absolute URL.
// get Resource object
Resource resource = resourceLoader.getResource(location);
// load BeanDefinition People
int count = loadBeanDefinitions(resource);
if (actualResources != null) {
// Add to actualResources in
actualResources.add(resource);
}
if (logger.isTraceEnabled()) {
logger.trace("Loaded " + count + " bean definitions from location [" + location + "]");
}
return count;
}
} @Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
} // ... Omit the relevant code
}

In the implementation method , Will eventually call int loadBeanDefinitions(Resource resource) This method , This method is implemented in subclasses

XmlBeanDefinitionReader

org.springframework.beans.factory.xml.XmlBeanDefinitionReader,XML File resource parser , It is concluded that BeanDefinition Configure the meta information object and register

Constructors

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
/**
* Disable authentication mode
*/
public static final int VALIDATION_NONE = XmlValidationModeDetector.VALIDATION_NONE; /**
* Automatically get validation mode
*/
public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO; /**
* DTD Verification mode
*/
public static final int VALIDATION_DTD = XmlValidationModeDetector.VALIDATION_DTD; /**
* XSD Verification mode
*/
public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD; /** Constants instance for this class. */
private static final Constants constants = new Constants(XmlBeanDefinitionReader.class); /**
* Verification mode , The default is automatic mode .
*/
private int validationMode = VALIDATION_AUTO; private boolean namespaceAware = false; private Class<? extends BeanDefinitionDocumentReader> documentReaderClass = DefaultBeanDefinitionDocumentReader.class; /**
* Exception handling during parsing
*/
private ProblemReporter problemReporter = new FailFastProblemReporter(); private ReaderEventListener eventListener = new EmptyReaderEventListener(); private SourceExtractor sourceExtractor = new NullSourceExtractor(); @Nullable
private NamespaceHandlerResolver namespaceHandlerResolver; private DocumentLoader documentLoader = new DefaultDocumentLoader(); @Nullable
private EntityResolver entityResolver; private ErrorHandler errorHandler = new SimpleSaxErrorHandler(logger); /**
* XML Verification mode detector
*/
private final XmlValidationModeDetector validationModeDetector = new XmlValidationModeDetector(); /**
* Current thread , Loading EncodedResource aggregate .
*/
private final ThreadLocal<Set<EncodedResource>> resourcesCurrentlyBeingLoaded = new NamedThreadLocal<>(
"XML bean definition resources currently being loaded"); /**
* Create new XmlBeanDefinitionReader for the given bean factory.
* @param registry the BeanFactory to load bean definitions into,
* in the form of a BeanDefinitionRegistry
*/
public XmlBeanDefinitionReader(BeanDefinitionRegistry registry) {
super(registry);
}
}

loadBeanDefinitions Method

loadBeanDefinitions(Resource resource) Method , analysis Resource Access to resources , The method is as follows :

@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
return loadBeanDefinitions(new EncodedResource(resource));
} 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);
} // <1> Gets the Resource Resource collection , Add current Resource, Prevent duplicate loading
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) { // Add the current resource to the record . If it already exists , Throw an exception , Prevent loops from loading the same resource
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
try {
// <2> from Resource The resource acquisition InputStream Stream object ( Support coding )
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// <3> 【 The core 】 Execute load Resource Resource process , It is concluded that BeanDefinition To register
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
// Closed flow
inputStream.close();
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
} finally {
// <4> Removes the currently loaded... From the current thread Resource object
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

take Resource Encapsulated into EncodedResource object , The goal is to make the resource object settable encoding

  1. Gets the Resource Resource collection , Add current Resource, Prevent duplicate loading
  2. from Resource The resource acquisition InputStream Stream object ( Support coding )
  3. 【 The core 】 call doLoadBeanDefinitions(InputSource inputSource, Resource resource) Method , Execute load Resource Resource process , It is concluded that BeanDefinition To register
  4. Removes the currently loaded... From the current thread Resource object

doLoadBeanDefinitions Method

doLoadBeanDefinitions(InputSource inputSource, Resource resource) Method , Execute load Resource Resource process , It is concluded that BeanDefinition To register , The method is as follows :

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// <1> obtain XML Document example
Document doc = doLoadDocument(inputSource, resource);
// <2> according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
// Omit catch Various anomalies
}
  1. call doLoadDocument(InputSource inputSource, Resource resource) Method , obtain XML Document example
  2. call registerBeanDefinitions(Document doc, Resource resource) Method , according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations

doLoadDocument Method

doLoadDocument(InputSource inputSource, Resource resource) Method , obtain Resource Resources correspond to XML Document example , The method is as follows :

protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
// <3> adopt DefaultDocumentLoader according to Resource Get one Document object
return this.documentLoader.loadDocument(inputSource,
getEntityResolver(), // <1> obtain `org.xml.sax.EntityResolver` Entity Resolver ,ResourceEntityResolver
this.errorHandler,
getValidationModeForResource(resource), isNamespaceAware()); // <2> obtain XML File validation mode , Guarantee XML The correctness of the document
}
  1. obtain org.xml.sax.EntityResolver Entity Resolver ,ResourceEntityResolver, according to publicId and systemId Get the corresponding DTD or XSD file , Used to deal with XML Document validation , This class compares The key , I'll talk about it later
  2. obtain XML File validation mode , Guarantee XML The correctness of the document , Usually XSD Pattern
    1. Gets the specified authentication mode , If specified manually , Then return directly , Usually not
    2. from Resource Get validation patterns from resources , according to XML Get the content of the file , If you include DOCTYPE The content is DTD Pattern , Otherwise XSD Pattern
    3. If the verification pattern has not been obtained yet , The default is XSD Pattern
  3. adopt DefaultDocumentLoader according to Resource Get one Document object
    1. establish DocumentBuilderFactory object factory, Turn on verification
    2. according to factory establish DocumentBuilder object builder, Set up EntityResolver( The first 1 Step created )、ErrorHandler attribute
    3. adopt builder Yes inputSource(Resource resources ) To analyze , Return to one Document object

The purpose of the above process is to obtain Resource Resources correspond to Document object , Need to go through two processes of verification and Analysis

registerBeanDefinitions Method

registerBeanDefinitions(Document doc, Resource resource) Method , according to Document example , It is concluded that BeanDefinition We need to register , Return the number of registrations , The method is as follows :

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// <1> establish BeanDefinitionDocumentReader object
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
// <2> Get registered BeanDefinition Number
int countBefore = getRegistry().getBeanDefinitionCount();
// <3> establish XmlReaderContext object ( Read Resource The context object of the resource )
// <4> according to Document、XmlReaderContext Parse out all of BeanDefinition And register
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// <5> Calculate newly registered BeanDefinition Number
return getRegistry().getBeanDefinitionCount() - countBefore;
}
  1. establish DefaultBeanDefinitionDocumentReader object documentReader
  2. Get registered BeanDefinition Number
  3. establish XmlReaderContext object ( Read Resource The context object of the resource ), Notice that this initializes a DefaultNamespaceHandlerResolver object , Used to handle custom tags (XML file ), Compare The key , stay Subsequent articles I'll talk about
  4. according to Document、XmlReaderContext Parse out all of BeanDefinition And register , call DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext) Method
  5. Calculate newly registered BeanDefinition Quantity and return

expand :DTD And XSD The difference between ?

DTD(Document Type Definition), Document type definition , by XML Verification mechanism of documents , Belong to XML Part of the document .DTD It's a guarantee XML An effective way to verify that the document format is correct , It defines the relevant XML The elements of the document 、 attribute 、 arrangement 、 The content type of the element and the hierarchy of the element . Actually DTD Equivalent to XML Medium “ vocabulary ” and “ grammar ”, We can compare XML Document and DTD file See if the document meets the specifications , Are elements and labels used correctly .

DTD At a certain stage, it promotes XML The development of , But there are some in it defects

  1. It's not used XML Format , It's about defining a format , The reusability of parser is poor ; and DTD There is no standard programming interface for building and accessing , This makes it difficult for the parser to parse simply DTD file
  2. DTD Less restrictions on the type of elements ; At the same time, other binding forces are also relatively weak
  3. DTD Poor scalability
  4. Based on regular expressions DTD The description ability of documents is limited

XSD(XML Schemas Definition), namely XML Schema Language , in the light of DTD The defects of the system are caused by W3C stay 2001 Launched in 2013 .XML Schema Is itself a XML file , It uses XML grammar , So it's easy to parse XSD file . be relative to DTD,XSD With the following advantage

  1. XML Schema be based on XML, There is no special grammar
  2. XML Schema Can be like other XML File like parsing and processing
  3. XML Schema Than DTD Provides a richer data type
  4. XML Schema Provide extensible data model
  5. XML Schema Support for comprehensive namespace
  6. XML Schema Support property groups

summary

We are Spring We usually define a in these two ways Bean: Resources oriented (XML、Properties) Annotation oriented , For the first way, if you define a XML file ,Spring Will pass XmlBeanDefinitionReader Load the XML file , Get the Resource Resources org.w3c.dom.Document object , This process will be verified 、 There are two steps to parsing

screwing Spring And IoC piece - BeanDefinition Loading phase of (XML file ) More articles about

  1. 【 screwing Spring】—— IoC It's loading BeanDefinition

    This paper is mainly based on Spring 5.0.6.RELEASE Abstract : Original source  http://cmsblogs.com/?p=2658 「 Brother Xiaoming 」, thank you ! As 「 Brother Xiaoming 」 A loyal reader of ,「 Grandma 」 Make a slight modification , Record ...

  2. 【 screwing Spring】----- IOC The analysis of bean label : Start the parsing process

    Original text :http://cmsblogs.com import Tag resolution is complete , Look again Spring The most complex and important label in the world bean The parsing process of tags . In the method parseDefaultElement ...

  3. 【 screwing Spring】----- IOC And load Bean

    Original text :http://cmsblogs.com Let's start with a familiar piece of code : ClassPathResource resource = new ClassPathResource("bean.xm ...

  4. 【 screwing Spring】—– IOC The analysis of Bean: analysis import label

    Original text :http://cmsblogs.com In blogs [ screwing Spring]----- IOC And register BeanDefinition In the analysis of ,Spring There are two kinds of analysis in Bean The way . If the root node ...

  5. 【 screwing Spring】----- IOC And obtain Document object

    Original text :http://cmsblogs.com stay XmlBeanDefinitionReader.doLoadDocument() Two things are done in the method , One is to call getValidationMode ...

  6. 【 screwing Spring】----- IOC And Get the validation model

    Original text :http://cmsblogs.com In the last blog [ screwing Spring]----- IOC And load Bean I mentioned , In the core logic method doLoadBeanDefinitions() It's mainly about doing ...

  7. 【 screwing Spring】—— IoC In depth understanding Spring IoC

    This paper is mainly based on Spring 5.0.6.RELEASE Abstract : Original source  http://svip.iocoder.cn/Spring/IoC-intro/ Learn at the beginning Spring When , We'll take it ...

  8. 【 screwing Spring】—— IoC And Spring Unified resource loading strategy

    This paper is mainly based on Spring 5.0.6.RELEASE Abstract : Original source  http://svip.iocoder.cn/Spring/IoC-load-Resource/ learning Java SE When ...

  9. Spring Load in ApplicationContext.xml How to file

    Spring Load in ApplicationContext.xml How to file original text :http://blog.csdn.net/snowjlz/article/details/8158560 1. utilize Cla ...

  10. 【 screwing Spring】----- IOC In depth understanding Spring IoC

    Learn at the beginning Spring When , We're in contact with IoC 了 , As Spring The first concept is , We must have a deep understanding of it before we interpret its source code , This article is [ screwing Spring] The first post in a series of blogs , The main ...

Random recommendation

  1. NewQuant The design of the ( One )—— Overall domain design

    NewQuant Design idea —— Overall domain analysis “ Domain-driven design (DDD)” He is a famous software engineering modeling expert Eric Evans An important concept put forward , yes “ Object oriented analysis design (OOAD)” The deepening of . When business logic becomes complex , System ...

  2. POJ 3243 Clever Y( discrete logarithm - Expand the small step big step algorithm )

    Description Little Y finds there is a very interesting formula in mathematics: XY mod Z = K Given X, ...

  3. Android_ User interface overview and data units

    One .UI Interface Overview UI, The user interface is a very important part of an application , It's the face of the app , The user's first impression of the application comes from the interface , So without a perfect user interface , It's hard to keep users . A good user interface will greatly improve the user's desire to use and maintain customer satisfaction ...

  4. Zabbix Installation and deployment --- Problem handling (php65.6.28 mysqli Report a mistake Handle )

    1)php65.6.28  mysqli  Report a mistake Handle http://www.xiaochengfu.com/index.php/index/detail/aid/92.html 2)linux Next p ...

  5. java webservice Summary of various implementation methods of

    One . be based on EJB Container management webservice :     1. So let's set up a Web services EndPoint: package cn.test.service.impl; import java ...

  6. HDU [P1150] Machine Schedule

    Bipartite graph matching for minimum point coverage Take two machines as two sets , Think of each task as a side map . So what we need is the minimum point cover of bipartite graph . But in the beginning WA 了 , The reason lies in , The topic requires the number of transformations , That is to say, with 0 The edge of the connection needs to be deleted . #includ ...

  7. Neo4j Community profile

    #*****************************************************************# Neo4j configuration## For more d ...

  8. Java - &quot;JUC Thread pool &quot; Callable And Future

    Java Multithreading series --“JUC Thread pool ”06 And Callable and Future Callable and Future brief introduction Callable and Future It's an interesting couple . When we need to get the thread's execution ...

  9. haoi2006_ Popular cattle _Solution

    Brief Solution: Strong connectivity tarjan+ Compression point + Judge if there is only one point , All the other points are out of range Detailed Solution: Think of a cow as a point b Can we get to the point a, be b Think a Welcome if all the points can be reached ...

  10. svn version management

    Code release scheme : 1, install , Optimize Software environment ,(nginx,lvs)  <------- O & M Engineer 2, Program code ( Constantly updated ).   <-------- Development Engineer ,( Development , Operation and maintenance can be released ) 3, ...