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 :
- establish BeanFactory object ( Bottom IoC Containers )
- establish BeanDefinitionReader object ( Resource resolver ), Related to chapter
1
Step created BeanFactory - adopt BeanDefinitionReader load XML Profile resources , Parse out all of BeanDefinition object
- 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 Readerorg.springframework.beans.factory.support.AbstractBeanDefinitionReader
abstract class , Provides a common implementation , The specific resource loading logic is implemented by subclassesorg.springframework.beans.factory.xml.XmlBeanDefinitionReader
,XML File resource parser , It is concluded that BeanDefinition Configure the meta information object and registerorg.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
- Gets the Resource Resource collection , Add current Resource, Prevent duplicate loading
- from Resource The resource acquisition InputStream Stream object ( Support coding )
- 【 The core 】 call
doLoadBeanDefinitions(InputSource inputSource, Resource resource)
Method , Execute load Resource Resource process , It is concluded that BeanDefinition To register - 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
}
- call
doLoadDocument(InputSource inputSource, Resource resource)
Method , obtain XML Document example - 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
}
- 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 - obtain XML File validation mode , Guarantee XML The correctness of the document , Usually XSD Pattern
- Gets the specified authentication mode , If specified manually , Then return directly , Usually not
- 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 - If the verification pattern has not been obtained yet , The default is XSD Pattern
- adopt DefaultDocumentLoader according to Resource Get one Document object
- establish DocumentBuilderFactory object
factory
, Turn on verification - according to
factory
establish DocumentBuilder objectbuilder
, Set up EntityResolver( The first1
Step created )、ErrorHandler attribute - adopt
builder
YesinputSource
(Resource resources ) To analyze , Return to one Document object
- establish DocumentBuilderFactory 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;
}
- establish DefaultBeanDefinitionDocumentReader object
documentReader
- Get registered BeanDefinition Number
- 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
- according to Document、XmlReaderContext Parse out all of BeanDefinition And register , call
DefaultBeanDefinitionDocumentReader#registerBeanDefinitions(Document doc, XmlReaderContext readerContext)
Method - 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 :
- 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
- DTD Less restrictions on the type of elements ; At the same time, other binding forces are also relatively weak
- DTD Poor scalability
- 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 :
- XML Schema be based on XML, There is no special grammar
- XML Schema Can be like other XML File like parsing and processing
- XML Schema Than DTD Provides a richer data type
- XML Schema Provide extensible data model
- XML Schema Support for comprehensive namespace
- 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
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 【 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 ...
- 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 ...
- 【 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
- 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 ...
- 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, ...
- 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 ...
- 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 ...
- 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 ...
- 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 ...
- Neo4j Community profile
#*****************************************************************# Neo4j configuration## For more d ...
- Java - "JUC Thread pool " 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 ...
- 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 ...
- 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, ...