Validation model analysis of spring IOC
write in front
This article continues the analysis on the basis of this article , as a supplement.
1: role
The function of verification is to ensure the correctness of the xml file. Only when the xml file is completely correct can the subsequent operations such as loading bean definitions continue.
2: xml validation mechanism
At present, the verification mechanisms of xml include DTD (Document Type Definition) and XSD (Xml Schema Definition). The former is earlier and XSD is later, because of various defects of DTD (such as few data types, weak scalability, and non-standard xml format resulting in parsing difficult), has been phased out and XSD has become mainstream.
3: Verification Process
For the convenience of debugging, paste the test code:
@Test
public void testBeanDefinitionLoad ( ) {
// Define resource
ClassPathResource classPathResource = new ClassPathResource ( "testbeandefinition.xml" ) ;
// Define IOC container
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory ( ) ;
// Define bean definition reader
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader ( defaultListableBeanFactory ) ; // Read bean definition
int from resource through bean definition reader
i = xmlBeanDefinitionReader . loadBeanDefinitions ( classPathResource ) ;
System . out . println ( "The number of bean definitions is: " + i ) ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
xml:
<?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 = " testBeanDefinitionBean "
class = " yudaosourcecode.spring.TestBeanDefinitionBean " > </ bean >
< bean id = " testBeanDefinitionBean1 "
class = " yudaosourcecode.spring.TestBeanDefinitionBean " > </ bean >
<!-- If you import yourself here, an org.springframework.beans.factory.BeanDefinitionStoreException will occur-->
<!--<import resource="testbeandefinition.xml"/>-->
</ beans >
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
The final call to the code:
org.springframework.beans.factory.xml.XmlBeanDefinitionReader
# doLoadDocument protected Document doLoadDocument ( InputSource inputSource , Resource resource ) throws Exception { return this.documentLoader.loadDocument ( inputSource , getEntityResolver ( ) , this.errorHandler , getValidationModeForResource ( resource ) _ _ _ _ _ _ _ _ _ _ _ _
, isNamespaceAware ( ) ) ;
}
- 1
- 2
- 3
- 4
- 5
The method will be called inside the methodgetValidationModeForResource
Get the verification mode, the source code is as follows:
org . springframework . beans . factory . xml . XmlBeanDefinitionReader#getValidationModeForResource
protected int getValidationModeForResource ( Resource resource ) {
// <2021-02-25 12:16> Get set validation mode
int validationModeToUse = getValidationMode ( ) ;
// if set The validation mode is not VALIDATION_AUTO,
// private int validationMode = VALIDATION_AUTO;
// public static final int VALIDATION_AUTO = XmlValidationModeDetector.VALIDATION_AUTO;
// public static final int VALIDATION_AUTO = 1;
// then use, otherwise continue
if ( validationModeToUse != VALIDATION_AUTO ) {
return validationModeToUse ;
}
// <2021-02-25 12:21> get the validation mode automatically from the resource
int detectedMode = detectValidationMode ( resource ) ;
// if it is not automatic use the automatically obtained
if ( detectedMode != VALIDATION_AUTO ) {
return detectedMode ;
}
// It is not set manually, and it is not obtained automatically, then the default XSD
// public static final int VALIDATION_XSD = XmlValidationModeDetector.VALIDATION_XSD;
// org.springframework.util.xml.XmlValidationModeDetector#VALIDATION_XSD
// public static final int VALIDATION_XSD = 3;
return VALIDATION_XSD ;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
<2021-02-25 12:16>
The source code is as follows:
org . springframework . beans . factory . xml . XmlBeanDefinitionReader#getValidationMode
public int getValidationMode ( ) {
// default is auto validation mode
// private int validationMode = VALIDATION_AUTO;
return this . validationMode ;
}
- 1
- 2
- 3
- 4
- 5
- 6
<2021-02-25 12:21>
Get the verification method from the xml file, the source code is as follows:
org . springframework . beans . factory . xml . XmlBeanDefinitionReader#detectValidationMode
protected int detectValidationMode ( Resource resource ) {
// unreadable, throws BeanDefinitionStoreException
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." ) ;
}
// Get the input stream
InputStream inputStream ;
try {
inputStream = resource . getInputStream ( ) ;
}
catch ( IOException ex ) {
. . . snip throw ex . . .
}
try {
// <2021-02-25 14:40> here is the actual location of the validation mode
return this . validationModeDetector . detectValidationMode ( inputStream ) ;
}
catch ( IOException ex ) {
. . . snip throw ex . . .
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
<2021-02-25 14:40>
Here, to actually get the location of the verification mode, we will explain in a separate part.
3.1: XmlValidationModeDetector
This is an independent object, no subclasses, no superclassesOf course after excluding java.lang.Object
. This part explains<2021-02-25 14:40>
The source code is as follows:
public int detectValidationMode ( InputStream inputStream ) throws IOException {
// Peek into the file to look for DOCTYPE.
BufferedReader reader = new BufferedReader ( new InputStreamReader ( inputStream ) ) ;
try {
// default is dtd
boolean isDtdValidated = false ;
String content ;
/ / Loop through each line to judge
while ( ( content = reader . readLine ( )) != null ) {
// process comments
content = consumeCommentTokens ( content ) ;
// if wrapped in comments or no content, continue
if ( this . inComment || ! StringUtils . hasText ( content ) ) {
continue ;
}
/ / If there is a DOCTYPE keyword, it is considered to be dtd, which is generally false here
// The following is the case where DOCTYPE is included
// <?xml version="1.0" encoding="UTF-8"?>
// <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
if (hasDoctype ( content ) ) {
isDtdValidated = true ;
break ;
}
// If it starts with < and is followed by a letter, it is true, because it is not what we need, but the normal definition content, such as <bean. ..
if ( hasOpeningTag ( content ) ) {
// End of meaningful data...
break ;
}
}
// If isDtdValidated is true then return dtd, otherwise xsd
return ( isDtdValidated ? VALIDATION_DTD : VALIDATION_XSD ) ;
}
catch ( CharConversionException ex) {
// Return to automatic validation mode if an exception occurs
return VALIDATION_AUTO ;
}
finally {
reader . close ( ) ;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
Then through here , see how the resource is loaded as a Document document object.